~jtaylor/ubuntu/maverick/tahoe-lafs/fix-848476

« back to all changes in this revision

Viewing changes to src/allmydata/test/test_cli.py

  • Committer: Bazaar Package Importer
  • Author(s): Jeremy Visser, Jeremy Visser, Fabrice Coutadeur
  • Date: 2010-03-04 19:37:54 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100304193754-2xjgls4n6nul3wz0
Tags: 1.6.1-0ubuntu1
[Jeremy Visser]
* Update to bugfix release 1.6.1 (LP: #529350).
  - Correct handling of small immutable directories.
  - Improved user interface messages and error reporting.
* debian/control: bump standards-version to 3.8.4. No changes required.
* debian/gbp.conf: deleted as it's a temporary file left over
* debian/watch: fixed to have the correct tarball name and avoid SUMO version

[Fabrice Coutadeur]
* Switch to dpkg-source 3.0 (quilt) format
* debian/reduce_build_dependencies.patch: converted from direct source
  changes done in 1.6.0 to reduce the required dependencies and not download
  them at build time.
* debian/rules: deleted get-orig-source target as the watch file has been
  fixed

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
 
29
29
timeout = 480 # deep_check takes 360s on Zandr's linksys box, others take > 240s
30
30
 
 
31
 
31
32
class CLI(unittest.TestCase):
32
33
    # this test case only looks at argument-processing and simple stuff.
33
34
    def test_options(self):
34
35
        fileutil.rm_dir("cli/test_options")
35
36
        fileutil.make_dirs("cli/test_options")
36
37
        fileutil.make_dirs("cli/test_options/private")
37
 
        open("cli/test_options/node.url","w").write("http://localhost:8080/\n")
 
38
        fileutil.write("cli/test_options/node.url", "http://localhost:8080/\n")
38
39
        filenode_uri = uri.WriteableSSKFileURI(writekey="\x00"*16,
39
40
                                               fingerprint="\x00"*32)
40
41
        private_uri = uri.DirectoryURI(filenode_uri).to_string()
41
 
        open("cli/test_options/private/root_dir.cap", "w").write(private_uri + "\n")
 
42
        fileutil.write("cli/test_options/private/root_dir.cap", private_uri + "\n")
42
43
        o = cli.ListOptions()
43
44
        o.parseOptions(["--node-directory", "cli/test_options"])
44
45
        self.failUnlessEqual(o['node-url'], "http://localhost:8080/")
158
159
        self.failUnless("file renewal secret: arpszxzc2t6kb4okkg7sp765xgkni5z7caavj7lta73vmtymjlxq" in output, output)
159
160
 
160
161
        fileutil.make_dirs("cli/test_dump_cap/private")
161
 
        f = open("cli/test_dump_cap/private/secret", "w")
162
 
        f.write("5s33nk3qpvnj2fw3z4mnm2y6fa\n")
163
 
        f.close()
 
162
        fileutil.write("cli/test_dump_cap/private/secret", "5s33nk3qpvnj2fw3z4mnm2y6fa\n")
164
163
        output = self._dump_cap("--client-dir", "cli/test_dump_cap",
165
164
                                u.to_string())
166
165
        self.failUnless("file renewal secret: arpszxzc2t6kb4okkg7sp765xgkni5z7caavj7lta73vmtymjlxq" in output, output)
252
251
        nodedir1 = "cli/test_catalog_shares/node1"
253
252
        sharedir = os.path.join(nodedir1, "storage", "shares", "mq", "mqfblse6m5a6dh45isu2cg7oji")
254
253
        fileutil.make_dirs(sharedir)
255
 
        f = open(os.path.join(sharedir, "8"), "wb")
256
 
        open("cli/test_catalog_shares/node1/storage/shares/mq/not-a-dir", "wb").close()
 
254
        fileutil.write("cli/test_catalog_shares/node1/storage/shares/mq/not-a-dir", "")
257
255
        # write a bogus share that looks a little bit like CHK
258
 
        f.write("\x00\x00\x00\x01" + "\xff" * 200) # this triggers an assert
259
 
        f.close()
 
256
        fileutil.write(os.path.join(sharedir, "8"),
 
257
                       "\x00\x00\x00\x01" + "\xff" * 200) # this triggers an assert
260
258
 
261
259
        nodedir2 = "cli/test_catalog_shares/node2"
262
260
        fileutil.make_dirs(nodedir2)
263
 
        open("cli/test_catalog_shares/node1/storage/shares/not-a-dir", "wb").close()
 
261
        fileutil.write("cli/test_catalog_shares/node1/storage/shares/not-a-dir", "")
264
262
 
265
263
        # now make sure that the 'catalog-shares' commands survives the error
266
264
        out, err = self._catalog_shares(nodedir1, nodedir2)
298
296
        self.failUnlessEqual(ga1("c:file"), ("CA", "file"))
299
297
        self.failUnlessEqual(ga1("c:dir/file"), ("CA", "dir/file"))
300
298
        self.failUnlessEqual(ga1("URI:stuff"), ("URI:stuff", ""))
 
299
        self.failUnlessEqual(ga1("URI:stuff/file"), ("URI:stuff", "file"))
301
300
        self.failUnlessEqual(ga1("URI:stuff:./file"), ("URI:stuff", "file"))
302
 
        self.failUnlessEqual(ga1("URI:stuff:./dir/file"),
303
 
                             ("URI:stuff", "dir/file"))
 
301
        self.failUnlessEqual(ga1("URI:stuff/dir/file"), ("URI:stuff", "dir/file"))
 
302
        self.failUnlessEqual(ga1("URI:stuff:./dir/file"), ("URI:stuff", "dir/file"))
304
303
        self.failUnlessRaises(common.UnknownAliasError, ga1, "missing:")
305
304
        self.failUnlessRaises(common.UnknownAliasError, ga1, "missing:dir")
306
305
        self.failUnlessRaises(common.UnknownAliasError, ga1, "missing:dir/file")
332
331
        self.failUnlessEqual(ga2("work:file"), ("WA", "file"))
333
332
        self.failUnlessEqual(ga2("work:dir/file"), ("WA", "dir/file"))
334
333
        self.failUnlessEqual(ga2("URI:stuff"), ("URI:stuff", ""))
 
334
        self.failUnlessEqual(ga2("URI:stuff/file"), ("URI:stuff", "file"))
335
335
        self.failUnlessEqual(ga2("URI:stuff:./file"), ("URI:stuff", "file"))
 
336
        self.failUnlessEqual(ga2("URI:stuff/dir/file"), ("URI:stuff", "dir/file"))
336
337
        self.failUnlessEqual(ga2("URI:stuff:./dir/file"), ("URI:stuff", "dir/file"))
337
338
        self.failUnlessRaises(common.UnknownAliasError, ga2, "missing:")
338
339
        self.failUnlessRaises(common.UnknownAliasError, ga2, "missing:dir")
369
370
        self.failUnlessRaises(common.UnknownAliasError, ga3, "missing:")
370
371
        self.failUnlessRaises(common.UnknownAliasError, ga3, "missing:dir")
371
372
        self.failUnlessRaises(common.UnknownAliasError, ga3, "missing:dir/file")
 
373
        # calling get_alias with a path that doesn't include an alias and
 
374
        # default set to something that isn't in the aliases argument should
 
375
        # raise an UnknownAliasError.
 
376
        def ga4(path):
 
377
            return get_alias(aliases, path, "badddefault:")
 
378
        self.failUnlessRaises(common.UnknownAliasError, ga4, "afile")
 
379
        self.failUnlessRaises(common.UnknownAliasError, ga4, "a/dir/path/")
 
380
 
 
381
        def ga5(path):
 
382
            old = common.pretend_platform_uses_lettercolon
 
383
            try:
 
384
                common.pretend_platform_uses_lettercolon = True
 
385
                retval = get_alias(aliases, path, "baddefault:")
 
386
            finally:
 
387
                common.pretend_platform_uses_lettercolon = old
 
388
            return retval
 
389
        self.failUnlessRaises(common.UnknownAliasError, ga5, "C:\\Windows")
372
390
 
373
391
 
374
392
class Help(unittest.TestCase):
474
492
        def _stash_urls(res):
475
493
            aliases = get_aliases(self.get_clientdir())
476
494
            node_url_file = os.path.join(self.get_clientdir(), "node.url")
477
 
            nodeurl = open(node_url_file, "r").read().strip()
 
495
            nodeurl = fileutil.read(node_url_file).strip()
478
496
            self.welcome_url = nodeurl
479
497
            uribase = nodeurl + "uri/"
480
498
            self.tahoe_url = uribase + urllib.quote(aliases["tahoe"])
523
541
        d.addCallback(_test_urls)
524
542
 
525
543
        def _remove_trailing_newline_and_create_alias(ign):
526
 
            f = open(aliasfile, "r")
527
 
            old = f.read()
528
 
            f.close()
529
544
            # ticket #741 is about a manually-edited alias file (which
530
545
            # doesn't end in a newline) being corrupted by a subsequent
531
546
            # "tahoe create-alias"
532
 
            f = open(aliasfile, "w")
533
 
            f.write(old.rstrip())
534
 
            f.close()
 
547
            old = fileutil.read(aliasfile)
 
548
            fileutil.write(aliasfile, old.rstrip())
535
549
            return self.do_cli("create-alias", "un-corrupted1")
536
550
        d.addCallback(_remove_trailing_newline_and_create_alias)
537
551
        def _check_not_corrupted1((rc,stdout,stderr)):
553
567
 
554
568
        def _remove_trailing_newline_and_add_alias(ign):
555
569
            # same thing, but for "tahoe add-alias"
556
 
            f = open(aliasfile, "r")
557
 
            old = f.read()
558
 
            f.close()
559
 
            f = open(aliasfile, "w")
560
 
            f.write(old.rstrip())
561
 
            f.close()
 
570
            old = fileutil.read(aliasfile)
 
571
            fileutil.write(aliasfile, old.rstrip())
562
572
            return self.do_cli("add-alias", "un-corrupted2", self.two_uri)
563
573
        d.addCallback(_remove_trailing_newline_and_add_alias)
564
574
        def _check_not_corrupted((rc,stdout,stderr)):
574
584
 
575
585
        return d
576
586
 
 
587
 
 
588
class Ln(GridTestMixin, CLITestMixin, unittest.TestCase):
 
589
    def _create_test_file(self):
 
590
        data = "puppies" * 1000
 
591
        path = os.path.join(self.basedir, "datafile")
 
592
        f = open(path, 'wb')
 
593
        f.write(data)
 
594
        f.close()
 
595
        self.datafile = path
 
596
 
 
597
    def test_ln_without_alias(self):
 
598
        # if invoked without an alias when the 'tahoe' alias doesn't
 
599
        # exist, 'tahoe ln' should output a useful error message and not
 
600
        # a stack trace
 
601
        self.basedir = "cli/Ln/ln_without_alias"
 
602
        self.set_up_grid()
 
603
        d = self.do_cli("ln", "from", "to")
 
604
        def _check((rc, out, err)):
 
605
            self.failUnlessEqual(rc, 1)
 
606
            self.failUnlessIn("error:", err)
 
607
        d.addCallback(_check)
 
608
        # Make sure that validation extends to the "to" parameter
 
609
        d.addCallback(lambda ign: self.do_cli("create-alias", "havasu"))
 
610
        d.addCallback(lambda ign: self._create_test_file())
 
611
        d.addCallback(lambda ign: self.do_cli("put", self.datafile,
 
612
                                              "havasu:from"))
 
613
        d.addCallback(lambda ign: self.do_cli("ln", "havasu:from", "to"))
 
614
        d.addCallback(_check)
 
615
        return d
 
616
 
 
617
    def test_ln_with_nonexistent_alias(self):
 
618
        # If invoked with aliases that don't exist, 'tahoe ln' should 
 
619
        # output a useful error message and not a stack trace.
 
620
        self.basedir = "cli/Ln/ln_with_nonexistent_alias"
 
621
        self.set_up_grid()
 
622
        d = self.do_cli("ln", "havasu:from", "havasu:to")
 
623
        def _check((rc, out, err)):
 
624
            self.failUnlessEqual(rc, 1)
 
625
            self.failUnlessIn("error:", err)
 
626
        d.addCallback(_check)
 
627
        # Make sure that validation occurs on the to parameter if the
 
628
        # from parameter passes.
 
629
        d.addCallback(lambda ign: self.do_cli("create-alias", "havasu"))
 
630
        d.addCallback(lambda ign: self._create_test_file())
 
631
        d.addCallback(lambda ign: self.do_cli("put", self.datafile,
 
632
                                              "havasu:from"))
 
633
        d.addCallback(lambda ign: self.do_cli("ln", "havasu:from", "huron:to"))
 
634
        d.addCallback(_check)
 
635
        return d
 
636
 
 
637
 
577
638
class Put(GridTestMixin, CLITestMixin, unittest.TestCase):
578
639
 
579
640
    def test_unlinked_immutable_stdin(self):
612
673
        rel_fn = os.path.join(self.basedir, "DATAFILE")
613
674
        abs_fn = os.path.abspath(rel_fn)
614
675
        # we make the file small enough to fit in a LIT file, for speed
615
 
        f = open(rel_fn, "w")
616
 
        f.write("short file")
617
 
        f.close()
 
676
        fileutil.write(rel_fn, "short file")
618
677
        d = self.do_cli("put", rel_fn)
619
678
        def _uploaded((rc,stdout,stderr)):
620
679
            readcap = stdout
645
704
        # we make the file small enough to fit in a LIT file, for speed
646
705
        DATA = "short file"
647
706
        DATA2 = "short file two"
648
 
        f = open(rel_fn, "w")
649
 
        f.write(DATA)
650
 
        f.close()
 
707
        fileutil.write(rel_fn, DATA)
651
708
 
652
709
        d = self.do_cli("create-alias", "tahoe")
653
710
 
726
783
        DATA2 = "two" * 100
727
784
        rel_fn = os.path.join(self.basedir, "DATAFILE")
728
785
        DATA3 = "three" * 100
729
 
        f = open(rel_fn, "w")
730
 
        f.write(DATA3)
731
 
        f.close()
 
786
        fileutil.write(rel_fn, DATA3)
732
787
 
733
788
        d = self.do_cli("put", "--mutable", stdin=DATA)
734
789
        def _created(res):
772
827
 
773
828
        DATA1 = "data" * 100
774
829
        fn1 = os.path.join(self.basedir, "DATA1")
775
 
        f = open(fn1, "w")
776
 
        f.write(DATA1)
777
 
        f.close()
 
830
        fileutil.write(fn1, DATA1)
778
831
        DATA2 = "two" * 100
779
832
        fn2 = os.path.join(self.basedir, "DATA2")
780
 
        f = open(fn2, "w")
781
 
        f.write(DATA2)
782
 
        f.close()
 
833
        fileutil.write(fn2, DATA2)
783
834
 
784
835
        d = self.do_cli("create-alias", "tahoe")
785
836
        d.addCallback(lambda res:
791
842
        d.addCallback(lambda (rc,out,err): self.failUnlessEqual(out, DATA2))
792
843
        return d
793
844
 
 
845
    def test_put_with_nonexistent_alias(self):
 
846
        # when invoked with an alias that doesn't exist, 'tahoe put'
 
847
        # should output a useful error message, not a stack trace
 
848
        self.basedir = "cli/Put/put_with_nonexistent_alias"
 
849
        self.set_up_grid()
 
850
        d = self.do_cli("put", "somefile", "fake:afile")
 
851
        def _check((rc, out, err)):
 
852
            self.failUnlessEqual(rc, 1)
 
853
            self.failUnlessIn("error:", err)
 
854
        d.addCallback(_check)
 
855
        return d
 
856
 
 
857
 
794
858
class List(GridTestMixin, CLITestMixin, unittest.TestCase):
795
859
    def test_list(self):
796
860
        self.basedir = "cli/List/list"
846
910
                          "trailing hyphen means unknown date")
847
911
        d.addCallback(lambda ign: self.do_cli("ls", "-l", "good"))
848
912
        d.addCallback(_check4)
 
913
        # listing a file as $DIRCAP/filename should work just like dir/filename
 
914
        d.addCallback(lambda ign: self.do_cli("ls", "-l", self.rooturi + "/good"))
 
915
        d.addCallback(_check4)
 
916
        # and similarly for $DIRCAP:./filename
 
917
        d.addCallback(lambda ign: self.do_cli("ls", "-l", self.rooturi + ":./good"))
 
918
        d.addCallback(_check4)
849
919
        def _check5((rc, out, err)):
850
920
            # listing a raw filecap should not explode, but it will have no
851
921
            # metadata, just the size
853
923
            self.failUnlessEqual("-r-- %d -" % len(small), out.strip())
854
924
        d.addCallback(lambda ign: self.do_cli("ls", "-l", self.goodcap))
855
925
        d.addCallback(_check5)
856
 
        return d
 
926
        unknown_immcap = "imm.URI:unknown"
 
927
        def _create_unknown(ign):
 
928
            nm = c0.nodemaker
 
929
            kids = {u"unknownchild-imm": (nm.create_from_cap(unknown_immcap), {})}
 
930
            return self.rootnode.create_subdirectory(u"unknown", initial_children=kids,
 
931
                                                     mutable=False)
 
932
        d.addCallback(_create_unknown)
 
933
        def _check6((rc, out, err)):
 
934
            # listing a directory referencing an unknown object should print
 
935
            # an extra message to stderr
 
936
            self.failUnlessEqual(rc, 0)
 
937
            self.failUnlessIn("?r-- ? - unknownchild-imm\n", out)
 
938
            self.failUnlessIn("included unknown objects", err)
 
939
        d.addCallback(lambda ign: self.do_cli("ls", "-l", "unknown"))
 
940
        d.addCallback(_check6)
 
941
        def _check7((rc, out, err)):
 
942
            # listing an unknown cap directly should print an extra message
 
943
            # to stderr (currently this only works if the URI starts with 'URI:'
 
944
            # after any 'ro.' or 'imm.' prefix, otherwise it will be confused
 
945
            # with an alias).
 
946
            self.failUnlessEqual(rc, 0)
 
947
            self.failUnlessIn("?r-- ? -\n", out)
 
948
            self.failUnlessIn("included unknown objects", err)
 
949
        d.addCallback(lambda ign: self.do_cli("ls", "-l", unknown_immcap))
 
950
        d.addCallback(_check7)
 
951
        return d
 
952
 
 
953
    def test_list_without_alias(self):
 
954
        # doing just 'tahoe ls' without specifying an alias or first
 
955
        # doing 'tahoe create-alias tahoe' should fail gracefully.
 
956
        self.basedir = "cli/List/list_without_alias"
 
957
        self.set_up_grid()
 
958
        d = self.do_cli("ls")
 
959
        def _check((rc, out, err)):
 
960
            self.failUnlessEqual(rc, 1)
 
961
            self.failUnlessIn("error:", err)
 
962
        d.addCallback(_check)
 
963
        return d
 
964
 
 
965
    def test_list_with_nonexistent_alias(self):
 
966
        # doing 'tahoe ls' while specifying an alias that doesn't already
 
967
        # exist should fail with an informative error message
 
968
        self.basedir = "cli/List/list_with_nonexistent_alias"
 
969
        self.set_up_grid()
 
970
        d = self.do_cli("ls", "nonexistent:")
 
971
        def _check((rc, out, err)):
 
972
            self.failUnlessEqual(rc, 1)
 
973
            self.failUnlessIn("error:", err)
 
974
            self.failUnlessIn("nonexistent", err)
 
975
        d.addCallback(_check)
 
976
        return d
 
977
 
857
978
 
858
979
class Mv(GridTestMixin, CLITestMixin, unittest.TestCase):
859
980
    def test_mv_behavior(self):
861
982
        self.set_up_grid()
862
983
        fn1 = os.path.join(self.basedir, "file1")
863
984
        DATA1 = "Nuclear launch codes"
864
 
        open(fn1, "wb").write(DATA1)
 
985
        fileutil.write(fn1, DATA1)
865
986
        fn2 = os.path.join(self.basedir, "file2")
866
987
        DATA2 = "UML diagrams"
867
 
        open(fn2, "wb").write(DATA2)
 
988
        fileutil.write(fn2, DATA2)
868
989
        # copy both files to the grid
869
990
        d = self.do_cli("create-alias", "tahoe")
870
991
        d.addCallback(lambda res:
950
1071
                              "mv moved the wrong thing"))
951
1072
        return d
952
1073
 
 
1074
    def test_mv_without_alias(self):
 
1075
        # doing 'tahoe mv' without explicitly specifying an alias or 
 
1076
        # creating the default 'tahoe' alias should fail with a useful
 
1077
        # error message.
 
1078
        self.basedir = "cli/Mv/mv_without_alias"
 
1079
        self.set_up_grid()
 
1080
        d = self.do_cli("mv", "afile", "anotherfile")
 
1081
        def _check((rc, out, err)):
 
1082
            self.failUnlessEqual(rc, 1)
 
1083
            self.failUnlessIn("error:", err)
 
1084
        d.addCallback(_check)
 
1085
        # check to see that the validation extends to the
 
1086
        # target argument by making an alias that will work with the first
 
1087
        # one.
 
1088
        d.addCallback(lambda ign: self.do_cli("create-alias", "havasu"))
 
1089
        def _create_a_test_file(ign):
 
1090
            self.test_file_path = os.path.join(self.basedir, "afile")
 
1091
            f = open(self.test_file_path, "wb")
 
1092
            f.write("puppies" * 100)
 
1093
            f.close()
 
1094
        d.addCallback(_create_a_test_file)
 
1095
        d.addCallback(lambda ign: self.do_cli("put", self.test_file_path,
 
1096
                                              "havasu:afile"))
 
1097
        d.addCallback(lambda ign: self.do_cli("mv", "havasu:afile",
 
1098
                                              "anotherfile"))
 
1099
        d.addCallback(_check)
 
1100
        return d
 
1101
 
 
1102
    def test_mv_with_nonexistent_alias(self):
 
1103
        # doing 'tahoe mv' with an alias that doesn't exist should fail 
 
1104
        # with an informative error message.
 
1105
        self.basedir = "cli/Mv/mv_with_nonexistent_alias"
 
1106
        self.set_up_grid()
 
1107
        d = self.do_cli("mv", "fake:afile", "fake:anotherfile")
 
1108
        def _check((rc, out, err)):
 
1109
            self.failUnlessEqual(rc, 1)
 
1110
            self.failUnlessIn("error:", err)
 
1111
            self.failUnlessIn("fake", err)
 
1112
        d.addCallback(_check)
 
1113
        # check to see that the validation extends to the
 
1114
        # target argument by making an alias that will work with the first
 
1115
        # one.
 
1116
        d.addCallback(lambda ign: self.do_cli("create-alias", "havasu"))
 
1117
        def _create_a_test_file(ign):
 
1118
            self.test_file_path = os.path.join(self.basedir, "afile")
 
1119
            f = open(self.test_file_path, "wb")
 
1120
            f.write("puppies" * 100)
 
1121
            f.close()
 
1122
        d.addCallback(_create_a_test_file)
 
1123
        d.addCallback(lambda ign: self.do_cli("put", self.test_file_path,
 
1124
                                              "havasu:afile"))
 
1125
        d.addCallback(lambda ign: self.do_cli("mv", "havasu:afile",
 
1126
                                              "fake:anotherfile"))
 
1127
        d.addCallback(_check)
 
1128
        return d
 
1129
 
 
1130
 
953
1131
class Cp(GridTestMixin, CLITestMixin, unittest.TestCase):
954
1132
 
955
1133
    def test_not_enough_args(self):
963
1141
 
964
1142
        fn1 = os.path.join(self.basedir, "Ärtonwall")
965
1143
        DATA1 = "unicode file content"
966
 
        open(fn1, "wb").write(DATA1)
 
1144
        fileutil.write(fn1, DATA1)
967
1145
 
968
1146
        fn2 = os.path.join(self.basedir, "Metallica")
969
1147
        DATA2 = "non-unicode file content"
970
 
        open(fn2, "wb").write(DATA2)
 
1148
        fileutil.write(fn2, DATA2)
971
1149
 
972
1150
        # Bug #534
973
1151
        # Assure that uploading a file whose name contains unicode character doesn't
1007
1185
        self.set_up_grid()
1008
1186
        outdir = os.path.join(self.basedir, "outdir")
1009
1187
        os.mkdir(outdir)
1010
 
        self.do_cli("create-alias", "tahoe")
1011
1188
        fn1 = os.path.join(self.basedir, "Metallica")
1012
1189
        fn2 = os.path.join(outdir, "Not Metallica")
1013
1190
        fn3 = os.path.join(outdir, "test2")
1014
1191
        DATA1 = "puppies" * 10000
1015
 
        open(fn1, "wb").write(DATA1)
1016
 
        d = self.do_cli("put", fn1)
 
1192
        fileutil.write(fn1, DATA1)
 
1193
 
 
1194
        d = self.do_cli("create-alias", "tahoe")
 
1195
        d.addCallback(lambda ign: self.do_cli("put", fn1))
1017
1196
        def _put_file((rc, out, err)):
1018
1197
            self.failUnlessEqual(rc, 0)
1019
1198
            # keep track of the filecap
1020
1199
            self.filecap = out.strip()
1021
1200
        d.addCallback(_put_file)
 
1201
 
1022
1202
        # Let's try copying this to the disk using the filecap
1023
1203
        #  cp FILECAP filename
1024
 
        d.addCallback(lambda res: self.do_cli("cp", self.filecap, fn2))
 
1204
        d.addCallback(lambda ign: self.do_cli("cp", self.filecap, fn2))
1025
1205
        def _copy_file((rc, out, err)):
1026
1206
            self.failUnlessEqual(rc, 0)
1027
 
            results = open(fn2, "r").read()
 
1207
            results = fileutil.read(fn2)
1028
1208
            self.failUnlessEqual(results, DATA1)
 
1209
        d.addCallback(_copy_file)
 
1210
 
1029
1211
        # Test with ./ (see #761)
1030
1212
        #  cp FILECAP localdir
1031
 
        d.addCallback(lambda res: self.do_cli("cp", self.filecap, outdir))
 
1213
        d.addCallback(lambda ign: self.do_cli("cp", self.filecap, outdir))
1032
1214
        def _resp((rc, out, err)):
1033
1215
            self.failUnlessEqual(rc, 1)
1034
1216
            self.failUnlessIn("error: you must specify a destination filename",
1035
1217
                              err)
1036
1218
        d.addCallback(_resp)
 
1219
 
1037
1220
        # Create a directory, linked at tahoe:test
1038
 
        d.addCallback(lambda res: self.do_cli("mkdir", "tahoe:test"))
 
1221
        d.addCallback(lambda ign: self.do_cli("mkdir", "tahoe:test"))
1039
1222
        def _get_dir((rc, out, err)):
1040
1223
            self.failUnlessEqual(rc, 0)
1041
1224
            self.dircap = out.strip()
1042
1225
        d.addCallback(_get_dir)
 
1226
 
1043
1227
        # Upload a file to the directory
1044
 
        d.addCallback(lambda res:
1045
 
            self.do_cli("put", fn1, "tahoe:test/test_file"))
 
1228
        d.addCallback(lambda ign:
 
1229
                      self.do_cli("put", fn1, "tahoe:test/test_file"))
1046
1230
        d.addCallback(lambda (rc, out, err): self.failUnlessEqual(rc, 0))
 
1231
 
1047
1232
        #  cp DIRCAP/filename localdir
1048
 
        d.addCallback(lambda res:
 
1233
        d.addCallback(lambda ign:
1049
1234
                      self.do_cli("cp",  self.dircap + "/test_file", outdir))
1050
1235
        def _get_resp((rc, out, err)):
1051
1236
            self.failUnlessEqual(rc, 0)
1052
 
            results = open(os.path.join(outdir, "test_file"), "r").read()
 
1237
            results = fileutil.read(os.path.join(outdir, "test_file"))
1053
1238
            self.failUnlessEqual(results, DATA1)
1054
1239
        d.addCallback(_get_resp)
 
1240
 
1055
1241
        #  cp -r DIRCAP/filename filename2
1056
 
        d.addCallback(lambda res:
 
1242
        d.addCallback(lambda ign:
1057
1243
                      self.do_cli("cp",  self.dircap + "/test_file", fn3))
1058
1244
        def _get_resp2((rc, out, err)):
1059
1245
            self.failUnlessEqual(rc, 0)
1060
 
            results = open(fn3, "r").read()
 
1246
            results = fileutil.read(fn3)
1061
1247
            self.failUnlessEqual(results, DATA1)
1062
1248
        d.addCallback(_get_resp2)
1063
1249
        return d
1064
1250
 
 
1251
    def test_cp_with_nonexistent_alias(self):
 
1252
        # when invoked with an alias or aliases that don't exist, 'tahoe cp'
 
1253
        # should output a sensible error message rather than a stack trace.
 
1254
        self.basedir = "cli/Cp/cp_with_nonexistent_alias"
 
1255
        self.set_up_grid()
 
1256
        d = self.do_cli("cp", "fake:file1", "fake:file2")
 
1257
        def _check((rc, out, err)):
 
1258
            self.failUnlessEqual(rc, 1)
 
1259
            self.failUnlessIn("error:", err)
 
1260
        d.addCallback(_check)
 
1261
        # 'tahoe cp' actually processes the target argument first, so we 
 
1262
        # need to check to make sure that validation extends to the 
 
1263
        # source argument.
 
1264
        d.addCallback(lambda ign: self.do_cli("create-alias", "tahoe"))
 
1265
        d.addCallback(lambda ign: self.do_cli("cp", "fake:file1",
 
1266
                                              "tahoe:file2"))
 
1267
        d.addCallback(_check)
 
1268
        return d
 
1269
 
 
1270
 
1065
1271
class Backup(GridTestMixin, CLITestMixin, StallMixin, unittest.TestCase):
1066
1272
 
1067
1273
    def writeto(self, path, data):
1068
 
        d = os.path.dirname(os.path.join(self.basedir, "home", path))
1069
 
        fileutil.make_dirs(d)
1070
 
        f = open(os.path.join(self.basedir, "home", path), "w")
1071
 
        f.write(data)
1072
 
        f.close()
 
1274
        full_path = os.path.join(self.basedir, "home", path)
 
1275
        fileutil.make_dirs(os.path.dirname(full_path))
 
1276
        fileutil.write(full_path, data)
1073
1277
 
1074
1278
    def count_output(self, out):
1075
1279
        mo = re.search(r"(\d)+ files uploaded \((\d+) reused\), "
1308
1512
        basedir = "cli/Backup/exclude_options"
1309
1513
        fileutil.make_dirs(basedir)
1310
1514
        nodeurl_path = os.path.join(basedir, 'node.url')
1311
 
        nodeurl = file(nodeurl_path, 'w')
1312
 
        nodeurl.write('http://example.net:2357/')
1313
 
        nodeurl.close()
 
1515
        fileutil.write(nodeurl_path, 'http://example.net:2357/')
1314
1516
 
1315
1517
        def _check_filtering(filtered, all, included, excluded):
1316
1518
            filtered = set(filtered)
1344
1546
        # read exclude patterns from file
1345
1547
        exclusion_string = "_darcs\n*py\n.svn"
1346
1548
        excl_filepath = os.path.join(basedir, 'exclusion')
1347
 
        excl_file = file(excl_filepath, 'w')
1348
 
        excl_file.write(exclusion_string)
1349
 
        excl_file.close()
 
1549
        fileutil.write(excl_filepath, exclusion_string)
1350
1550
        backup_options = cli.BackupOptions()
1351
1551
        backup_options.parseOptions(['--exclude-from', excl_filepath, '--node-directory',
1352
1552
                                     basedir, 'from', 'to'])
1468
1668
        d.addErrback(_cleanup)
1469
1669
        return d
1470
1670
 
 
1671
    def test_backup_without_alias(self):
 
1672
        # 'tahoe backup' should output a sensible error message when invoked
 
1673
        # without an alias instead of a stack trace.
 
1674
        self.basedir = os.path.dirname(self.mktemp())
 
1675
        self.set_up_grid()
 
1676
        source = os.path.join(self.basedir, "file1")
 
1677
        d = self.do_cli('backup', source, source)
 
1678
        def _check((rc, out, err)):
 
1679
            self.failUnlessEqual(rc, 1)
 
1680
            self.failUnlessIn("error:", err)
 
1681
        d.addCallback(_check)
 
1682
        return d
 
1683
 
 
1684
    def test_backup_with_nonexistent_alias(self):
 
1685
        # 'tahoe backup' should output a sensible error message when invoked
 
1686
        # with a nonexistent alias.
 
1687
        self.basedir = os.path.dirname(self.mktemp())
 
1688
        self.set_up_grid()
 
1689
        source = os.path.join(self.basedir, "file1")
 
1690
        d = self.do_cli("backup", source, "nonexistent:" + source)
 
1691
        def _check((rc, out, err)):
 
1692
            self.failUnlessEqual(rc, 1)
 
1693
            self.failUnlessIn("error:", err)
 
1694
            self.failUnlessIn("nonexistent", err)
 
1695
        d.addCallback(_check)
 
1696
        return d
 
1697
 
1471
1698
 
1472
1699
class Check(GridTestMixin, CLITestMixin, unittest.TestCase):
1473
1700
 
1762
1989
 
1763
1990
        return d
1764
1991
 
 
1992
    def test_check_without_alias(self):
 
1993
        # 'tahoe check' should output a sensible error message if it needs to
 
1994
        # find the default alias and can't
 
1995
        self.basedir = "cli/Check/check_without_alias"
 
1996
        self.set_up_grid()
 
1997
        d = self.do_cli("check")
 
1998
        def _check((rc, out, err)):
 
1999
            self.failUnlessEqual(rc, 1)
 
2000
            self.failUnlessIn("error:", err)
 
2001
        d.addCallback(_check)
 
2002
        d.addCallback(lambda ign: self.do_cli("deep-check"))
 
2003
        d.addCallback(_check)
 
2004
        return d
 
2005
 
 
2006
    def test_check_with_nonexistent_alias(self):
 
2007
        # 'tahoe check' should output a sensible error message if it needs to
 
2008
        # find an alias and can't.
 
2009
        self.basedir = "cli/Check/check_with_nonexistent_alias"
 
2010
        self.set_up_grid()
 
2011
        d = self.do_cli("check", "nonexistent:")
 
2012
        def _check((rc, out, err)):
 
2013
            self.failUnlessEqual(rc, 1)
 
2014
            self.failUnlessIn("error:", err)
 
2015
            self.failUnlessIn("nonexistent", err)
 
2016
        d.addCallback(_check)
 
2017
        return d
 
2018
 
 
2019
 
1765
2020
class Errors(GridTestMixin, CLITestMixin, unittest.TestCase):
1766
2021
    def test_get(self):
1767
2022
        self.basedir = "cli/Errors/get"
1795
2050
 
1796
2051
        return d
1797
2052
 
 
2053
 
 
2054
class Get(GridTestMixin, CLITestMixin, unittest.TestCase):
 
2055
    def test_get_without_alias(self):
 
2056
        # 'tahoe get' should output a useful error message when invoked
 
2057
        # without an explicit alias and when the default 'tahoe' alias
 
2058
        # hasn't been created yet.
 
2059
        self.basedir = "cli/Get/get_without_alias"
 
2060
        self.set_up_grid()
 
2061
        d = self.do_cli('get', 'file')
 
2062
        def _check((rc, out, err)):
 
2063
            self.failUnlessEqual(rc, 1)
 
2064
            self.failUnlessIn("error:", err)
 
2065
        d.addCallback(_check)
 
2066
        return d
 
2067
 
 
2068
    def test_get_with_nonexistent_alias(self):
 
2069
        # 'tahoe get' should output a useful error message when invoked with
 
2070
        # an explicit alias that doesn't exist.
 
2071
        self.basedir = "cli/Get/get_with_nonexistent_alias"
 
2072
        self.set_up_grid()
 
2073
        d = self.do_cli("get", "nonexistent:file")
 
2074
        def _check((rc, out, err)):
 
2075
            self.failUnlessEqual(rc, 1)
 
2076
            self.failUnlessIn("error:", err)
 
2077
            self.failUnlessIn("nonexistent", err)
 
2078
        d.addCallback(_check)
 
2079
        return d
 
2080
 
 
2081
 
 
2082
class Manifest(GridTestMixin, CLITestMixin, unittest.TestCase):
 
2083
    def test_manifest_without_alias(self):
 
2084
        # 'tahoe manifest' should output a useful error message when invoked
 
2085
        # without an explicit alias when the default 'tahoe' alias is
 
2086
        # missing.
 
2087
        self.basedir = "cli/Manifest/manifest_without_alias"
 
2088
        self.set_up_grid()
 
2089
        d = self.do_cli("manifest")
 
2090
        def _check((rc, out, err)):
 
2091
            self.failUnlessEqual(rc, 1)
 
2092
            self.failUnlessIn("error:", err)
 
2093
        d.addCallback(_check)
 
2094
        return d
 
2095
 
 
2096
    def test_manifest_with_nonexistent_alias(self):
 
2097
        # 'tahoe manifest' should output a useful error message when invoked
 
2098
        # with an explicit alias that doesn't exist.
 
2099
        self.basedir = "cli/Manifest/manifest_with_nonexistent_alias"
 
2100
        self.set_up_grid()
 
2101
        d = self.do_cli("manifest", "nonexistent:")
 
2102
        def _check((rc, out, err)):
 
2103
            self.failUnlessEqual(rc, 1)
 
2104
            self.failUnlessIn("error:", err)
 
2105
            self.failUnlessIn("nonexistent", err)
 
2106
        d.addCallback(_check)
 
2107
        return d
 
2108
 
 
2109
 
 
2110
class Mkdir(GridTestMixin, CLITestMixin, unittest.TestCase):
 
2111
    def test_mkdir_with_nonexistent_alias(self):
 
2112
        # when invoked with an alias that doesn't exist, 'tahoe mkdir'
 
2113
        # should output a sensible error message rather than a stack 
 
2114
        # trace.
 
2115
        self.basedir = "cli/Mkdir/mkdir_with_nonexistent_alias"
 
2116
        self.set_up_grid()
 
2117
        d = self.do_cli("mkdir", "havasu:")
 
2118
        def _check((rc, out, err)):
 
2119
            self.failUnlessEqual(rc, 1)
 
2120
            self.failUnlessIn("error:", err)
 
2121
        d.addCallback(_check)
 
2122
        return d
 
2123
 
 
2124
 
 
2125
class Rm(GridTestMixin, CLITestMixin, unittest.TestCase):
 
2126
    def test_rm_without_alias(self):
 
2127
        # 'tahoe rm' should behave sensibly when invoked without an explicit
 
2128
        # alias before the default 'tahoe' alias has been created.
 
2129
        self.basedir = "cli/Rm/rm_without_alias"
 
2130
        self.set_up_grid()
 
2131
        d = self.do_cli("rm", "afile")
 
2132
        def _check((rc, out, err)):
 
2133
            self.failUnlessIn("error:", err)
 
2134
            self.failUnlessEqual(rc, 1)
 
2135
        d.addCallback(_check)
 
2136
        return d
 
2137
 
 
2138
    def test_rm_with_nonexistent_alias(self):
 
2139
        # 'tahoe rm' should behave sensibly when invoked with an explicit
 
2140
        # alias that doesn't exist.
 
2141
        self.basedir = "cli/Rm/rm_with_nonexistent_alias"
 
2142
        self.set_up_grid()
 
2143
        d = self.do_cli("rm", "nonexistent:afile")
 
2144
        def _check((rc, out, err)):
 
2145
            self.failUnlessEqual(rc, 1)
 
2146
            self.failUnlessIn("error:", err)
 
2147
            self.failUnlessIn("nonexistent", err)
 
2148
        d.addCallback(_check)
 
2149
        return d
 
2150
 
 
2151
 
1798
2152
class Stats(GridTestMixin, CLITestMixin, unittest.TestCase):
1799
2153
    def test_empty_directory(self):
1800
2154
        self.basedir = "cli/Stats/empty_directory"
1822
2176
        d.addCallback(_check_stats)
1823
2177
 
1824
2178
        return d
 
2179
 
 
2180
    def test_stats_without_alias(self):
 
2181
        # when invoked with no explicit alias and before the default 'tahoe'
 
2182
        # alias is created, 'tahoe stats' should output an informative error
 
2183
        # message, not a stack trace.
 
2184
        self.basedir = "cli/Stats/stats_without_alias"
 
2185
        self.set_up_grid()
 
2186
        d = self.do_cli("stats")
 
2187
        def _check((rc, out, err)):
 
2188
            self.failUnlessEqual(rc, 1)
 
2189
            self.failUnlessIn("error:", err)
 
2190
        d.addCallback(_check)
 
2191
        return d
 
2192
 
 
2193
    def test_stats_with_nonexistent_alias(self):
 
2194
        # when invoked with an explicit alias that doesn't exist, 
 
2195
        # 'tahoe stats' should output a useful error message.
 
2196
        self.basedir = "cli/Stats/stats_with_nonexistent_alias"
 
2197
        self.set_up_grid()
 
2198
        d = self.do_cli("stats", "havasu:")
 
2199
        def _check((rc, out, err)):
 
2200
            self.failUnlessEqual(rc, 1)
 
2201
            self.failUnlessIn("error:", err)
 
2202
        d.addCallback(_check)
 
2203
        return d
 
2204
 
 
2205
 
 
2206
class Webopen(GridTestMixin, CLITestMixin, unittest.TestCase):
 
2207
    def test_webopen_with_nonexistent_alias(self):
 
2208
        # when invoked with an alias that doesn't exist, 'tahoe webopen'
 
2209
        # should output an informative error message instead of a stack 
 
2210
        # trace.
 
2211
        self.basedir = "cli/Webopen/webopen_with_nonexistent_alias"
 
2212
        self.set_up_grid()
 
2213
        d = self.do_cli("webopen", "fake:")
 
2214
        def _check((rc, out, err)):
 
2215
            self.failUnlessEqual(rc, 1)
 
2216
            self.failUnlessIn("error:", err)
 
2217
        d.addCallback(_check)
 
2218
        return d