2 from twisted.trial import unittest
4 from allmydata.util import fileutil
5 from allmydata.scripts.common import get_aliases
6 from allmydata.scripts import cli, runner
7 from allmydata.test.no_network import GridTestMixin
8 from allmydata.util.encodingutil import quote_output, get_io_encoding
9 from .test_cli import CLITestMixin
11 timeout = 480 # deep_check takes 360s on Zandr's linksys box, others take > 240s
13 class CreateAlias(GridTestMixin, CLITestMixin, unittest.TestCase):
15 def _test_webopen(self, args, expected_url):
17 o.parseOptions(["--node-directory", self.get_clientdir(), "webopen"]
20 rc = cli.webopen(o, urls.append)
21 self.failUnlessReallyEqual(rc, 0)
22 self.failUnlessReallyEqual(len(urls), 1)
23 self.failUnlessReallyEqual(urls[0], expected_url)
25 def test_create(self):
26 self.basedir = "cli/CreateAlias/create"
28 aliasfile = os.path.join(self.get_clientdir(), "private", "aliases")
30 d = self.do_cli("create-alias", "tahoe")
31 def _done((rc,stdout,stderr)):
32 self.failUnless("Alias 'tahoe' created" in stdout)
34 aliases = get_aliases(self.get_clientdir())
35 self.failUnless("tahoe" in aliases)
36 self.failUnless(aliases["tahoe"].startswith("URI:DIR2:"))
38 d.addCallback(lambda res: self.do_cli("create-alias", "two:"))
41 aliases = get_aliases(self.get_clientdir())
42 node_url_file = os.path.join(self.get_clientdir(), "node.url")
43 nodeurl = fileutil.read(node_url_file).strip()
44 self.welcome_url = nodeurl
45 uribase = nodeurl + "uri/"
46 self.tahoe_url = uribase + urllib.quote(aliases["tahoe"])
47 self.tahoe_subdir_url = self.tahoe_url + "/subdir"
48 self.two_url = uribase + urllib.quote(aliases["two"])
49 self.two_uri = aliases["two"]
50 d.addCallback(_stash_urls)
52 d.addCallback(lambda res: self.do_cli("create-alias", "two")) # dup
53 def _check_create_duplicate((rc,stdout,stderr)):
54 self.failIfEqual(rc, 0)
55 self.failUnless("Alias 'two' already exists!" in stderr)
56 aliases = get_aliases(self.get_clientdir())
57 self.failUnlessReallyEqual(aliases["two"], self.two_uri)
58 d.addCallback(_check_create_duplicate)
60 d.addCallback(lambda res: self.do_cli("add-alias", "added", self.two_uri))
61 def _check_add((rc,stdout,stderr)):
62 self.failUnlessReallyEqual(rc, 0)
63 self.failUnless("Alias 'added' added" in stdout)
64 d.addCallback(_check_add)
66 # check add-alias with a duplicate
67 d.addCallback(lambda res: self.do_cli("add-alias", "two", self.two_uri))
68 def _check_add_duplicate((rc,stdout,stderr)):
69 self.failIfEqual(rc, 0)
70 self.failUnless("Alias 'two' already exists!" in stderr)
71 aliases = get_aliases(self.get_clientdir())
72 self.failUnlessReallyEqual(aliases["two"], self.two_uri)
73 d.addCallback(_check_add_duplicate)
75 # check create-alias and add-alias with invalid aliases
76 def _check_invalid((rc,stdout,stderr)):
77 self.failIfEqual(rc, 0)
78 self.failUnlessIn("cannot contain", stderr)
80 for invalid in ['foo:bar', 'foo bar', 'foobar::']:
81 d.addCallback(lambda res, invalid=invalid: self.do_cli("create-alias", invalid))
82 d.addCallback(_check_invalid)
83 d.addCallback(lambda res, invalid=invalid: self.do_cli("add-alias", invalid, self.two_uri))
84 d.addCallback(_check_invalid)
87 self._test_webopen([], self.welcome_url)
88 self._test_webopen(["/"], self.tahoe_url)
89 self._test_webopen(["tahoe:"], self.tahoe_url)
90 self._test_webopen(["tahoe:/"], self.tahoe_url)
91 self._test_webopen(["tahoe:subdir"], self.tahoe_subdir_url)
92 self._test_webopen(["-i", "tahoe:subdir"],
93 self.tahoe_subdir_url+"?t=info")
94 self._test_webopen(["tahoe:subdir/"], self.tahoe_subdir_url + '/')
95 self._test_webopen(["tahoe:subdir/file"],
96 self.tahoe_subdir_url + '/file')
97 self._test_webopen(["--info", "tahoe:subdir/file"],
98 self.tahoe_subdir_url + '/file?t=info')
99 # if "file" is indeed a file, then the url produced by webopen in
100 # this case is disallowed by the webui. but by design, webopen
101 # passes through the mistake from the user to the resultant
103 self._test_webopen(["tahoe:subdir/file/"], self.tahoe_subdir_url + '/file/')
104 self._test_webopen(["two:"], self.two_url)
105 d.addCallback(_test_urls)
107 def _remove_trailing_newline_and_create_alias(ign):
108 # ticket #741 is about a manually-edited alias file (which
109 # doesn't end in a newline) being corrupted by a subsequent
110 # "tahoe create-alias"
111 old = fileutil.read(aliasfile)
112 fileutil.write(aliasfile, old.rstrip())
113 return self.do_cli("create-alias", "un-corrupted1")
114 d.addCallback(_remove_trailing_newline_and_create_alias)
115 def _check_not_corrupted1((rc,stdout,stderr)):
116 self.failUnless("Alias 'un-corrupted1' created" in stdout, stdout)
118 # the old behavior was to simply append the new record, causing a
119 # line that looked like "NAME1: CAP1NAME2: CAP2". This won't look
120 # like a valid dircap, so get_aliases() will raise an exception.
121 aliases = get_aliases(self.get_clientdir())
122 self.failUnless("added" in aliases)
123 self.failUnless(aliases["added"].startswith("URI:DIR2:"))
124 # to be safe, let's confirm that we don't see "NAME2:" in CAP1.
125 # No chance of a false-negative, because the hyphen in
126 # "un-corrupted1" is not a valid base32 character.
127 self.failIfIn("un-corrupted1:", aliases["added"])
128 self.failUnless("un-corrupted1" in aliases)
129 self.failUnless(aliases["un-corrupted1"].startswith("URI:DIR2:"))
130 d.addCallback(_check_not_corrupted1)
132 def _remove_trailing_newline_and_add_alias(ign):
133 # same thing, but for "tahoe add-alias"
134 old = fileutil.read(aliasfile)
135 fileutil.write(aliasfile, old.rstrip())
136 return self.do_cli("add-alias", "un-corrupted2", self.two_uri)
137 d.addCallback(_remove_trailing_newline_and_add_alias)
138 def _check_not_corrupted((rc,stdout,stderr)):
139 self.failUnless("Alias 'un-corrupted2' added" in stdout, stdout)
141 aliases = get_aliases(self.get_clientdir())
142 self.failUnless("un-corrupted1" in aliases)
143 self.failUnless(aliases["un-corrupted1"].startswith("URI:DIR2:"))
144 self.failIfIn("un-corrupted2:", aliases["un-corrupted1"])
145 self.failUnless("un-corrupted2" in aliases)
146 self.failUnless(aliases["un-corrupted2"].startswith("URI:DIR2:"))
147 d.addCallback(_check_not_corrupted)
149 def test_create_unicode(self):
150 self.basedir = "cli/CreateAlias/create_unicode"
154 etudes_arg = u"\u00E9tudes".encode(get_io_encoding())
155 lumiere_arg = u"lumi\u00E8re.txt".encode(get_io_encoding())
156 except UnicodeEncodeError:
157 raise unittest.SkipTest("A non-ASCII command argument could not be encoded on this platform.")
159 d = self.do_cli("create-alias", etudes_arg)
160 def _check_create_unicode((rc, out, err)):
161 self.failUnlessReallyEqual(rc, 0)
162 self.failUnlessReallyEqual(err, "")
163 self.failUnlessIn("Alias %s created" % quote_output(u"\u00E9tudes"), out)
165 aliases = get_aliases(self.get_clientdir())
166 self.failUnless(aliases[u"\u00E9tudes"].startswith("URI:DIR2:"))
167 d.addCallback(_check_create_unicode)
169 d.addCallback(lambda res: self.do_cli("ls", etudes_arg + ":"))
170 def _check_ls1((rc, out, err)):
171 self.failUnlessReallyEqual(rc, 0)
172 self.failUnlessReallyEqual(err, "")
173 self.failUnlessReallyEqual(out, "")
174 d.addCallback(_check_ls1)
176 d.addCallback(lambda res: self.do_cli("put", "-", etudes_arg + ":uploaded.txt",
177 stdin="Blah blah blah"))
179 d.addCallback(lambda res: self.do_cli("ls", etudes_arg + ":"))
180 def _check_ls2((rc, out, err)):
181 self.failUnlessReallyEqual(rc, 0)
182 self.failUnlessReallyEqual(err, "")
183 self.failUnlessReallyEqual(out, "uploaded.txt\n")
184 d.addCallback(_check_ls2)
186 d.addCallback(lambda res: self.do_cli("get", etudes_arg + ":uploaded.txt"))
187 def _check_get((rc, out, err)):
188 self.failUnlessReallyEqual(rc, 0)
189 self.failUnlessReallyEqual(err, "")
190 self.failUnlessReallyEqual(out, "Blah blah blah")
191 d.addCallback(_check_get)
193 # Ensure that an Unicode filename in an Unicode alias works as expected
194 d.addCallback(lambda res: self.do_cli("put", "-", etudes_arg + ":" + lumiere_arg,
195 stdin="Let the sunshine In!"))
197 d.addCallback(lambda res: self.do_cli("get",
198 get_aliases(self.get_clientdir())[u"\u00E9tudes"] + "/" + lumiere_arg))
199 def _check_get2((rc, out, err)):
200 self.failUnlessReallyEqual(rc, 0)
201 self.failUnlessReallyEqual(err, "")
202 self.failUnlessReallyEqual(out, "Let the sunshine In!")
203 d.addCallback(_check_get2)
207 # TODO: test list-aliases, including Unicode