def test_create(self): """ You can create a directory from a template """ t_root = FilePath(self.mktemp()) t_root.makedirs() d1 = t_root.child('dir1') d1.makedirs() f1 = d1.child('foo') f1.setContent('foo content') d2 = d1.child('dir2') d2.makedirs() f2 = d2.child('bar') f2.setContent('bar content') dst = FilePath(self.mktemp()) d = Directory(dst.path) # fake template root d.template_root = t_root d.create('dir1') self.assertTrue(dst.exists()) self.assertEqual(dst.child('foo').getContent(), 'foo content') self.assertTrue(dst.child('dir2').exists()) self.assertEqual(dst.child('dir2').child('bar').getContent(), 'bar content')
def test_twistd(self): """ Should run twistd with the given arguments """ runner = Runner() fake_twistd = FilePath(self.mktemp()) fake_twistd.setContent('#!%s\n' 'import sys, os\n' 'print " ".join(sys.argv[1:])\n' 'print os.environ["FOO"]\n' 'print os.path.abspath(os.curdir)\n' 'sys.stdout.flush()\n' 'sys.stderr.write("error\\n")\n' 'print "stdout"\n' 'sys.exit(4)\n' % sys.executable) fake_twistd.chmod(0777) runner._twistdBin = lambda: fake_twistd.path path = FilePath(self.mktemp()) path.makedirs() d = runner.twistd(['foo', 'bar', 'baz'], env={'FOO': 'foo value'}, path=path.path) def check(result): out, err, code = result self.assertEqual(code, 4) self.assertEqual(out, 'foo bar baz\n' 'foo value\n' '%s\n' 'stdout\n' % path.path) self.assertEqual(err, 'error\n') return d.addCallback(check)
def test_deferred_result(self): """ ``DeployScript.main`` returns a ``Deferred`` on success. """ temp = FilePath(self.mktemp()) temp.makedirs() application_config_path = temp.child(b"app.yml") application_config_path.setContent(safe_dump({ u"version": 1, u"applications": {}, })) deployment_config_path = temp.child(b"deploy.yml") deployment_config_path.setContent(safe_dump({ u"version": 1, u"nodes": {}, })) options = DeployOptions() options.parseOptions([ deployment_config_path.path, application_config_path.path]) script = DeployScript() dummy_reactor = object() self.assertEqual( None, self.successResultOf(script.main(dummy_reactor, options)) )
def test_null_environment(self): """ A container that does not include any environment variables contains an empty ``environment`` in the return ``Unit``. """ docker_dir = FilePath(self.mktemp()) docker_dir.makedirs() docker_dir.child(b"Dockerfile").setContent( b"FROM scratch\n" b"MAINTAINER [email protected]\n" b'CMD ["/bin/doesnotexist"]' ) name = random_name(self) image = DockerImageBuilder(test=self, source_dir=docker_dir) d = image.build() def image_built(image_name): client = self.make_client() self.create_container(client, name, image_name) self.addCleanup(client.remove, name) return client.list() d.addCallback(image_built) def got_list(units): unit = [unit for unit in units if unit.name == name][0] self.assertIsNone(unit.environment) d.addCallback(got_list) return d
def test_insertImages(self): """ L{formulaeToImages} replaces any elements with the I{latexformula} class with I{img} elements which refer to external images generated based on the latex in the original elements. """ parent = Element('div') base = FilePath(self.mktemp()) base.makedirs() macros = Element('span') macros.setAttribute('class', 'latexmacros') text = Text() text.data = 'foo' macros.appendChild(text) parent.appendChild(macros) formula = Element('span') formula.setAttribute('class', 'latexformula') text = Text() text.data = 'bar' formula.appendChild(text) parent.appendChild(formula) # Avoid actually executing the commands to generate images from the # latex. It might be nice to have some assertions about what commands # are executed, or perhaps even execute them and make sure an image # file is created, but that is a task for another day. commands = [] formulaeToImages(parent, base.path, _system=commands.append) self.assertEqual( parent.toxml(), '<div><span><br/><img src="latexformula0.png"/><br/></span></div>')
def test_json_to_yaml(self): """ Running `crossbar convert` with a YAML config file will convert it to JSON. """ cbdir = FilePath(self.mktemp()) cbdir.makedirs() config_file = cbdir.child("config.json") config_file.setContent(b"""{ "foo": { "bar": "spam", "baz": { "foo": "cat" } } }""") cli.run("crossbar", ["convert", "--config={}".format(config_file.path)]) self.assertIn( ("YAML formatted configuration written"), self.stdout.getvalue()) with open(cbdir.child("config.yaml").path) as f: self.assertEqual(f.read(), """foo: bar: spam baz: foo: cat """)
def test_load_error_on_unreadable_key_file(self): """ A ``PathError`` is raised if the key file path given to ``CertificateAuthority.from_path`` cannot be opened for reading. """ path = FilePath(self.mktemp()) path.makedirs() crt_path = path.child(b"cluster.crt") crt_file = crt_path.open(b'w') crt_file.write(b"dummy") crt_file.close() key_path = path.child(b"cluster.key") key_file = key_path.open(b'w') key_file.write(b"dummy") key_file.close() # make file unreadable key_path.chmod(64) e = self.assertRaises( PathError, CertificateAuthority.from_path, path ) expected = ( b"Private key file {path} could not be opened. " b"Check file permissions." ).format(path=key_path.path) self.assertEqual(str(e), expected)
class MakeCredentialsTests(SynchronousTestCase): def setUp(self): self.path = FilePath(self.mktemp()) self.path.makedirs() self.patch(certificate, "_generateKey", lambda: testKey) def _makeCredentials(self): return certificate.makeCredentials(self.path, u"*****@*****.**") def test_makeCredentials(self): """Making credentials creates a key with matching certificate and writes it to disk under the given path. """ self.assertRaises(IOError, certificate.getContextFactory, self.path) self._makeCredentials() certificate.getContextFactory(self.path) def test_makeCredentialsMultipleTimes(self): """Attempting to generate credentials when the credentials file exists already raises OSError. """ self.assertRaises(IOError, certificate.getContextFactory, self.path) self._makeCredentials() certificate.getContextFactory(self.path) self.assertRaises(OSError, self._makeCredentials) certificate.getContextFactory(self.path)
def test_saveKeysha256(self): """ L{_saveKey} will generate key fingerprint in L{FingerprintFormats.SHA256-BASE64} format if explicitly specified. """ base = FilePath(self.mktemp()) base.makedirs() filename = base.child('id_rsa').path key = Key.fromString(privateRSA_openssh) _saveKey(key, {'filename': filename, 'pass': '******', 'format': 'sha256-base64'}) self.assertEqual( self.stdout.getvalue(), "Your identification has been saved in %s\n" "Your public key has been saved in %s.pub\n" "The key fingerprint in <FingerprintFormats=SHA256_BASE64> is:\n" "ryaugIFT0B8ItuszldMEU7q14rG/wj9HkRosMeBWkts=\n" % ( filename, filename)) self.assertEqual( key.fromString( base.child('id_rsa').getContent(), None, 'passphrase'), key) self.assertEqual( Key.fromString(base.child('id_rsa.pub').getContent()), key.public())
class VoluminousTests(TestCase): def setUp(self): self.tmpdir = FilePath(self.mktemp()) self.tmpdir.makedirs() def test_create_volume(self): dvol = VoluminousOptions() dvol.parseOptions(ARGS + ["-p", self.tmpdir.path, "init", "foo"]) self.assertTrue(self.tmpdir.child("foo").exists()) self.assertTrue(self.tmpdir.child("foo").child("branches") .child("master").exists()) self.assertEqual(dvol.voluminous.getOutput()[-1], "Created volume foo\nCreated branch foo/master") # Verify operation with `list` dvol.parseOptions(ARGS + ["-p", self.tmpdir.path, "list"]) header, rest = self._parse_list_output(dvol) expected_volumes = [["*", "foo", "master"]] self.assertEqual( sorted(expected_volumes), sorted(rest), ) def test_create_volume_already_exists(self): dvol = VoluminousOptions() # Create the repository twice, second time should have the error expected_output = "Error: volume foo already exists" dvol.parseOptions(ARGS + ["-p", self.tmpdir.path, "init", "foo"]) try: dvol.parseOptions(ARGS + ["-p", self.tmpdir.path, "init", "foo"]) self.assertEqual(dvol.voluminous.getOutput()[-1], expected_output) except CalledProcessErrorWithOutput, error: self.assertIn(expected_output, error.original.output) self.assertTrue(error.original.returncode != 0)
def test_saveEncryptedDeprecation(self): """ Persisting data with encryption is deprecated. """ tempDir = FilePath(self.mktemp()) tempDir.makedirs() persistedPath = tempDir.child('epersisttest.python') data = b'once I was the king of spain' persistance = sob.Persistent(data, 'test-data') persistance.save(filename=persistedPath.path, passphrase=b'some-pass') # Check deprecation message. warnings = self.flushWarnings([persistance._saveTemp]) self.assertEqual(1, len(warnings)) self.assertIs(DeprecationWarning, warnings[0]['category']) self.assertEqual( 'Saving encrypted persisted data is deprecated since ' 'Twisted 15.5.0', warnings[0]['message']) # Check that data is still valid, even if we are deprecating this # functionality. loadedData = sob.load( persistedPath.path, persistance.style, b'some-pass') self.assertEqual(data, loadedData) self.flushWarnings([sob.load])
def test_saveKeyECDSA(self): """ L{_saveKey} writes the private and public parts of a key to two different files and writes a report of this to standard out. Test with ECDSA key. """ base = FilePath(self.mktemp()) base.makedirs() filename = base.child('id_ecdsa').path key = Key.fromString(privateECDSA_openssh) _saveKey(key, {'filename': filename, 'pass': '******', 'format': 'md5-hex'}) self.assertEqual( self.stdout.getvalue(), "Your identification has been saved in %s\n" "Your public key has been saved in %s.pub\n" "The key fingerprint in <FingerprintFormats=MD5_HEX> is:\n" "e2:3b:e8:1c:f8:c9:c7:de:8b:c0:00:68:2e:c9:2c:8a\n" % ( filename, filename)) self.assertEqual( key.fromString( base.child('id_ecdsa').getContent(), None, 'passphrase'), key) self.assertEqual( Key.fromString(base.child('id_ecdsa.pub').getContent()), key.public())
def test_inputNewVersionWithDefault(self): """ L{inputNewVersionWithDefault} should prompt for a new version number, using C{raw_input}, finding the current version number in a I{NEWS.txt} file in the grandparent of the C{initPath} of the project it is passed and supplying that as a default. """ projectPath = FilePath(self.mktemp()).child('FakeProject') projectPath.makedirs() projectPath.child('NEWS.txt').setContent('0.9.99') packagePath = projectPath.child('fakeproject') initPath = packagePath.child('__init__.py') project = Project(name="FakeProject", initPath=initPath, package=None, version=None) def checkPrompt(prompt): self.assertEqual(prompt, "New version for FakeProject (default 0.9.99)? ") return "" self.assertEqual( inputNewVersionWithDefault(project, raw_input=checkPrompt), (0, 9, 99)) self.assertEqual( inputNewVersionWithDefault(project, raw_input=lambda _: "6.7.89"), (6, 7, 89))
def _makeTree(self): parent = FilePath(self.mktemp()) parent.makedirs() sub = parent.child('sub') sub.makedirs() subsub = sub.child('sub sub') subsub.makedirs() parent.child('one.png').setContent("one") sub.child("two.png").setContent("two") subsub.child("three.png").setContent("three") t = {} t['md5one'] = hashlib.md5("one").hexdigest() t['md5two'] = hashlib.md5("two").hexdigest() t['md5three'] = hashlib.md5("three").hexdigest() t['md5replacement'] = hashlib.md5("replacement").hexdigest() temp = sub.child('style.css') original = """\ div { background-image: url(http://127.0.0.1/not-modified.png); } td { background-image: url(https://127.0.0.1/not-modified.png); } p { background-image: url(../one.png); } q { background-image: url(two.png); } b { background-image: url(sub%20sub/three.png); } i { background-image: url(/sub/sub%20sub/three.png); } """ temp.setContent(original) t['md5original'] = hashlib.md5(original).hexdigest() return parent, t
def test_functional(self): """ It works """ root = FilePath(self.mktemp()) root.makedirs() foo = root.child('foo') foo.setContent('#!%s\n' 'import sys, os\n' 'print sys.argv[1]\n' 'print sys.stdin.read()\n' % (sys.executable,)) foo.chmod(0777) history = [] runner = ScriptRunner(root.path, history.append) r = runner.run('foo', ['something'], 'guts') def check(proto): self.assertEqual(proto.stdout, 'something\nguts\n') self.assertEqual(proto.stderr, '') self.assertTrue(len(history) > 0) def eb(res): print res print '' for i in history: if i.key in [1,2,3]: print i.data['line'] return res return r.done.addCallback(check).addErrback(eb)
def test_doFile_withFilenameGenerator(self): base = FilePath(self.mktemp()) base.makedirs() def filenameGenerator(originalFileName, outputExtension): name = os.path.splitext(FilePath(originalFileName).basename())[0] return base.child(name + outputExtension).path templ = dom.parse(open(d['template'])) tree.doFile(self.file, self.linkrel, d['ext'], d['baseurl'], templ, d, filenameGenerator) self.assertXMLEqual( """\ <?xml version="1.0" ?><!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head><title>Twisted Documentation: My Test Lore Input</title></head> <body bgcolor="white"> <h1 class="title">My Test Lore Input</h1> <div class="content"> <span/> <p>A Body.</p> </div> <a href="index.xhtml">Index</a> </body> </html>""", base.child("simple.xhtml").getContent())
def test_getProcessor(self): base = FilePath(self.mktemp()) base.makedirs() input = base.child("simple3.html") FilePath(__file__).sibling("simple3.html").copyTo(input) options = { 'template': sp('template.tpl'), 'ext': '.xhtml', 'baseurl': 'burl', 'filenameMapping': None } p = process.getProcessor(default, "html", options) p(input.path, self.linkrel) self.assertXMLEqual( """\ <?xml version="1.0" ?><!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head><title>Twisted Documentation: My Test Lore Input</title></head> <body bgcolor="white"> <h1 class="title">My Test Lore Input</h1> <div class="content"> <span/> <p>A Body.</p> </div> <a href="index.xhtml">Index</a> </body> </html>""", base.child("simple3.xhtml").getContent())
def test_add_with_environment(self): """ ``DockerClient.add`` accepts an environment object whose ID and variables are used when starting a docker image. """ docker_dir = FilePath(self.mktemp()) docker_dir.makedirs() docker_dir.child(b"Dockerfile").setContent( b"FROM busybox\n" b'CMD ["/bin/sh", "-c", ' b'"while true; do env && echo WOOT && sleep 1; done"]' ) expected_variables = frozenset({"key1": "value1", "key2": "value2"}.items()) unit_name = random_name(self) image = DockerImageBuilder(test=self, source_dir=docker_dir) d = image.build() def image_built(image_name): return self.start_container( unit_name=unit_name, image_name=image_name, environment=Environment(variables=expected_variables) ) d.addCallback(image_built) def started(_): output = "" while True: output += Client().logs(self.namespacing_prefix + unit_name) if "WOOT" in output: break assertContainsAll(output, test_case=self, needles=["{}={}\n".format(k, v) for k, v in expected_variables]) d.addCallback(started) return d
def pathEntryTree(self, tree): """ Create some files in a hierarchy, based on a dictionary describing those files. The resulting hierarchy will be placed onto sys.path for the duration of the test. @param tree: A dictionary representing a directory structure. Keys are strings, representing filenames, dictionary values represent directories, string values represent file contents. @return: another dictionary similar to the input, with file content strings replaced with L{FilePath} objects pointing at where those contents are now stored. """ def makeSomeFiles(pathobj, dirdict): pathdict = {} for (key, value) in dirdict.items(): child = pathobj.child(key) if isinstance(value, bytes): pathdict[key] = child child.setContent(value) elif isinstance(value, dict): child.createDirectory() pathdict[key] = makeSomeFiles(child, value) else: raise ValueError("only strings and dicts allowed as values") return pathdict base = FilePath(self.mktemp().encode("utf-8")) base.makedirs() result = makeSomeFiles(base, tree) # On Python 3, sys.path cannot include byte paths: self.replaceSysPath([base.path.decode("utf-8")] + sys.path) self.replaceSysModules(sys.modules.copy()) return result
def test_branch_multi_volumes(self, volumes): """ Always show the last checked-out branch for all volumes in ``list``. """ tmpdir = FilePath(self.mktemp()) tmpdir.makedirs() dvol = VoluminousOptions() for volume, branch in volumes: dvol.parseOptions(ARGS + ["-p", tmpdir.path, "init", volume]) dvol.parseOptions(ARGS + ["-p", tmpdir.path, "commit", "-m", "hello"]) dvol.parseOptions(ARGS + ["-p", tmpdir.path, "checkout", "-b", branch]) dvol.parseOptions(ARGS + ["-p", tmpdir.path, "list"]) lines = dvol.voluminous.getOutput()[-1].split("\n") header, rest = lines[0], lines[1:] expected_volumes = [[volume, branch] for volume, branch in volumes] # `init` activates the volume, so the last initialized volume is the # active one. expected_volumes[-1] = [ '*', expected_volumes[-1][0], expected_volumes[-1][1]] self.assertEqual(['VOLUME', 'BRANCH', 'CONTAINERS'], header.split()) self.assertEqual( sorted(expected_volumes), sorted([line.split() for line in rest]), )
def test_load_error_on_unreadable_key_file(self): """ A ``PathError`` is raised if the key file path given to ``RootCredential.from_path`` cannot be opened for reading. """ path = FilePath(self.mktemp()) path.makedirs() crt_path = path.child(AUTHORITY_CERTIFICATE_FILENAME) crt_file = crt_path.open(b'w') crt_file.write(b"dummy") crt_file.close() key_path = path.child(AUTHORITY_KEY_FILENAME) key_file = key_path.open(b'w') key_file.write(b"dummy") key_file.close() # make file unreadable key_path.chmod(0o100) e = self.assertRaises( PathError, RootCredential.from_path, path ) expected = ( "Unable to load certificate authority file. " "Permission denied {path}" ).format(path=key_path.path) self.assertEqual(str(e), expected)
class Tests(SynchronousTestCase): def setUp(self): self.options = options_type() self.scratch_directory = FilePath(self.mktemp()) self.scratch_directory.makedirs() self.sample_content = yaml.safe_dump({ u"control-service": { u"hostname": u"10.0.0.1", u"port": 4524, }, u"version": 1, }) self.config = self.scratch_directory.child('dataset-config.yml') self.config.setContent(self.sample_content) def test_default_config_file(self): """ The default config file is a FilePath with path ``/etc/flocker/agent.yml``. """ self.options.parseOptions([]) self.assertEqual( self.options["agent-config"], FilePath("/etc/flocker/agent.yml")) def test_custom_config_file(self): """ The ``--config-file`` command-line option allows configuring the config file. """ self.options.parseOptions( [b"--agent-config", b"/etc/foo.yml"]) self.assertEqual( self.options["agent-config"], FilePath("/etc/foo.yml"))
def test_directory(self): """ A directory can exist """ root = FilePath(self.mktemp()) root.makedirs() root.chmod(0777) stdout, stderr, code = self.runScript(['inspect'], json.dumps({ 'kind': 'file', 'path': root.path, })) data = json.loads(stdout) self.assertEqual(data['kind'], 'file') self.assertEqual(data['path'], root.path) self.assertEqual(data['exists'], True) self.assertEqual(data['filetype'], 'dir') self.assertEqual(data['owner'], pwd.getpwuid(os.geteuid()).pw_name) self.assertEqual(data['group'], grp.getgrgid(os.getegid()).gr_name) self.assertEqual(data['perms'], '0777') root.restat() self.assertEqual(data['ctime'], int(root.statinfo.st_ctime)) self.assertEqual(type(data['ctime']), int) self.assertEqual(data['mtime'], int(root.statinfo.st_mtime)) self.assertEqual(type(data['mtime']), int) self.assertEqual(data['atime'], int(root.statinfo.st_atime)) self.assertEqual(type(data['atime']), int)
def test_unix_already_listening_cant_delete(self): """ A config with type = "unix" will create an endpoint for a UNIX socket at the given path, and delete it if required. If it can't delete it, it will raise an exception. """ parent_fp = FilePath("/tmp").child(uuid4().hex) parent_fp.makedirs() fp = parent_fp.child(uuid4().hex) # Something is already there fp.setContent(b"") fp.chmod(0o544) parent_fp.chmod(0o544) reactor = SelectReactor() config = { "type": "unix", "path": fp.path } with self.assertRaises(OSError) as e: create_listening_endpoint_from_config(config, self.cbdir, reactor, self.log) self.assertEqual(e.exception.errno, 13) # Permission Denied parent_fp.chmod(0o777) parent_fp.remove()
def make_site(self): p = FilePath(self.mktemp().decode("ascii")) p.makedirs() chargebee_secret = p.child(b"chargebee-key.secret") chargebee_secret.setContent(b"foo") stripe_publishable = p.child(b"stripe-key.publishable") stripe_publishable.setContent(b"bar") stripe_secret = p.child(b"stripe-key.secret") stripe_secret.setContent(b"baz") options = SiteOptions(self.reactor) options.parseOptions([ b"--chargebee-domain", b"localhost", b"--chargebee-site-name", b"some-site", b"--chargebee-secret-api-key-path", chargebee_secret.path, b"--chargebee-plan-id", b"foo-bar", b"--chargebee-gateway-account-id", b"gw_baz", b"--stripe-publishable-api-key-path", stripe_publishable.path, b"--site-logs-path", b"httpd.log", b"--secure-port", b"tcp:0", b"--subscription-manager", b"http://127.0.0.1:8888/", b"--cross-domain", self.origin, b"--wormhole-result-path", self.mktemp(), b"--signup-failure-address", u"*****@*****.**", ]) return site_for_options(self.reactor, options)
class _UnixFixHome(object): """ Mixin class to fix the HOME environment variable to something usable. @ivar home: FilePath pointing at C{homePath}. @type home: L{FilePath} @ivar homePath: relative path to the directory used as HOME during the tests. @type homePath: C{str} """ def setUp(self): path = self.mktemp() self.home = FilePath(path) self.homePath = os.path.join(*self.home.segmentsFrom(FilePath("."))) if len(self.home.path) >= 70: # UNIX_MAX_PATH is 108, and the socket file is generally of length # 30, so we can't rely on mktemp... self.homePath = "_tmp" self.home = FilePath(self.homePath) self.home.makedirs() self.savedEnviron = os.environ.copy() os.environ["HOME"] = self.homePath def tearDown(self): os.environ.clear() os.environ.update(self.savedEnviron) self.home.remove()
def test_saveKey(self): """ L{_saveKey} writes the private and public parts of a key to two different files and writes a report of this to standard out. """ base = FilePath(self.mktemp()) base.makedirs() filename = base.child('id_rsa').path key = Key.fromString(privateRSA_openssh) _saveKey( key.keyObject, {'filename': filename, 'pass': '******'}) self.assertEqual( self.stdout.getvalue(), "Your identification has been saved in %s\n" "Your public key has been saved in %s.pub\n" "The key fingerprint is:\n" "3d:13:5f:cb:c9:79:8a:93:06:27:65:bc:3d:0b:8f:af\n" % ( filename, filename)) self.assertEqual( key.fromString( base.child('id_rsa').getContent(), None, 'passphrase'), key) self.assertEqual( Key.fromString(base.child('id_rsa.pub').getContent()), key.public())
def test_list_with_missing_image(self): """ ``DockerClient.list()`` can list containers whose image is missing. The resulting output may be inaccurate, but that's OK: this only happens for non-running containers, who at worst we're going to restart anyway. """ path = FilePath(self.mktemp()) path.makedirs() path.child(b"Dockerfile.in").setContent( b"FROM busybox\nCMD /bin/true\n") image_name = DockerImageBuilder(test=self, source_dir=path, cleanup=False).build() name = random_name(self) d = self.start_container(unit_name=name, image_name=image_name, expected_states=(u'inactive',)) def stopped_container_exists(_): # Remove the image: docker_client = Client() docker_client.remove_image(image_name, force=True) # Should be able to still list the container: client = self.make_client() listed = client.list() listed.addCallback(lambda results: self.assertIn( (name, "inactive"), [(unit.name, unit.activation_state) for unit in results])) return listed d.addCallback(stopped_container_exists) return d
def test_load_error_on_unreadable_key_file(self): """ A ``PathError`` is raised if the key file path given to ``UserCredential.from_path`` cannot be opened for reading. """ path = FilePath(self.mktemp()) path.makedirs() crt_path = path.child(self.cert_file_name) crt_file = crt_path.open(b'w') crt_file.write(b"dummy") crt_file.close() key_path = path.child(self.key_file_name) key_file = key_path.open(b'w') key_file.write(b"dummy") key_file.close() # make file unreadable key_path.chmod(0o100) e = self.assertRaises( PathError, cls.from_path, path, **kwargs ) expected = ( "Private key file could not be opened. " "Permission denied {path}" ).format(path=key_path.path) self.assertEqual(str(e), expected)
def flocker_deploy(test_case, deployment_config, application_config): """ Run ``flocker-deploy`` with given configuration files. :param test_case: The ``TestCase`` running this unit test. :param dict deployment_config: The desired deployment configuration. :param dict application_config: The desired application configuration. """ # This is duplicate code, see # https://clusterhq.atlassian.net/browse/FLOC-1903 control_node = environ.get("FLOCKER_ACCEPTANCE_CONTROL_NODE") certificate_path = environ["FLOCKER_ACCEPTANCE_API_CERTIFICATES_PATH"] if control_node is None: raise SkipTest("Set control node address using " "FLOCKER_ACCEPTANCE_CONTROL_NODE environment variable.") temp = FilePath(test_case.mktemp()) temp.makedirs() deployment = temp.child(b"deployment.yml") deployment.setContent(safe_dump(deployment_config)) application = temp.child(b"application.yml") application.setContent(safe_dump(application_config)) check_call([b"flocker-deploy", b"--certificates-directory", certificate_path, control_node, deployment.path, application.path])
def test_load_error_on_non_existent_certificate_file(self): """ A ``PathError`` is raised if the certificate file path given to ``UserCredential.from_path`` does not exist. """ path = FilePath(self.mktemp()) path.makedirs() e = self.assertRaises( PathError, cls.from_path, path, **kwargs ) expected = ("Certificate file could not be opened. " "No such file or directory " "{path}").format( path=path.child(self.cert_file_name).path) self.assertEqual(str(e), expected)
def test_mount_root(self): """Mountpoints are children of the mount root.""" mount_root = FilePath(self.mktemp()) mount_root.makedirs() pool = StoragePool(reactor, create_zfs_pool(self), mount_root) service = service_for_pool(self, pool) volume = service.get(MY_VOLUME) d = pool.create(volume) def gotFilesystem(filesystem): self.assertEqual(filesystem.get_path(), mount_root.child(volume_to_dataset(volume))) d.addCallback(gotFilesystem) return d
def test_saveKeyEmptyPassphrase(self): """ L{_saveKey} will choose an empty string for the passphrase if no-passphrase is C{True}. """ base = FilePath(self.mktemp()) base.makedirs() filename = base.child('id_rsa').path key = Key.fromString(privateRSA_openssh) _saveKey(key, { 'filename': filename, 'no-passphrase': True, 'format': 'md5-hex' }) self.assertEqual( key.fromString(base.child('id_rsa').getContent(), None, b''), key)
def test_verify_ca_path_no_match_fails(self): """ With a CA file that does not match any CA, connection to the OpenStack servers fails. """ path = FilePath(self.mktemp()) path.makedirs() RootCredential.initialize(path, b"mycluster") try: cls, kwargs = get_blockdeviceapi_args( ProviderType.openstack, backend='openstack', auth_plugin='password', password='******', peer_verify=True, peer_ca_path=path.child(AUTHORITY_CERTIFICATE_FILENAME).path) except InvalidConfig as e: raise SkipTest(str(e)) self.assertFalse(self._authenticates_ok(kwargs['cinder_client']))
def _pathOption(self): """ Helper for the I{--path} tests which creates a directory and creates an L{Options} object which uses that directory as its static filesystem root. @return: A two-tuple of a L{FilePath} referring to the directory and the value associated with the C{'root'} key in the L{Options} instance after parsing a I{--path} option. """ path = FilePath(self.mktemp()) path.makedirs() options = Options() options.parseOptions(['--path', path.path]) root = options['root'] return path, root
def test_trialPathInsert(self): """ The trial script adds the current working directory to sys.path so that it's able to import modules from it. """ script = self.bin.child("trial") if not script.exists(): raise SkipTest("Script tests do not apply to installed configuration.") cwd = getcwd() self.addCleanup(chdir, cwd) testDir = FilePath(self.mktemp()) testDir.makedirs() chdir(testDir.path) testDir.child("foo.py").setContent("") output = outputFromPythonScript(script, "foo") self.assertIn("PASSED", output)
def test_twistdPathInsert(self): """ The twistd script adds the current working directory to sys.path so that it's able to import modules from it. """ script = self.bin.child("twistd") if not script.exists(): raise SkipTest("Script tests do not apply to installed configuration.") cwd = getcwd() self.addCleanup(chdir, cwd) testDir = FilePath(self.mktemp()) testDir.makedirs() chdir(testDir.path) testDir.child("bar.tac").setContent("import sys\n" "print sys.path\n") output = outputFromPythonScript(script, "-ny", "bar.tac") self.assertIn(repr(testDir.path), output)
def test_saveKeyEd25519EmptyPassphrase(self): """ L{_saveKey} will choose an empty string for the passphrase if no-passphrase is C{True}. """ base = FilePath(self.mktemp()) base.makedirs() filename = base.child("id_ed25519").path key = Key.fromString(privateEd25519_openssh_new) _saveKey(key, { "filename": filename, "no-passphrase": True, "format": "md5-hex" }) self.assertEqual( key.fromString(base.child("id_ed25519").getContent(), None), key)
def test_invalid_json_to_yaml(self): """ Running `crossbar convert` with an invalid JSON config file will error saying it is invalid. """ cbdir = FilePath(self.mktemp()) cbdir.makedirs() config_file = cbdir.child("config.json") config_file.setContent(b"""{{{{{{{{""") with self.assertRaises(SystemExit) as e: cli.run("crossbar", ["convert", "--config={}".format(config_file.path)]) self.assertEqual(e.exception.args[0], 1) self.assertIn(("not seem to be proper JSON"), self.stdout.getvalue())
def test_overridden_cluster_id(self): """ If a ``cluster_id`` is passed to ``RootCredential.initialize``, it is used as the value for the generated certificate's *organizational unit* field. """ path = FilePath(self.mktemp()) path.makedirs() cluster_id = UUID("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa") RootCredential.initialize( path, b"overridecluster", cluster_id=cluster_id, ) ca = RootCredential.from_path(path) self.assertEqual(cluster_id, UUID(ca.organizational_unit))
def test_saveKeyNoFilename(self): """ When no path is specified, it will ask for the path used to store the key. """ base = FilePath(self.mktemp()) base.makedirs() keyPath = base.child('custom_key').path self.patch(__builtin__, 'raw_input', lambda _: keyPath) key = Key.fromString(privateRSA_openssh) _saveKey(key, {'filename': None, 'no-passphrase': True}) persistedKeyContent = base.child('custom_key').getContent() persistedKey = key.fromString(persistedKeyContent, None, b'') self.assertEqual(key, persistedKey)
def build(self, dockerfile_variables=None): """ Build an image and tag it in the local Docker repository. :param dict dockerfile_variables: A dictionary of replacements which will be applied to a `Dockerfile.in` template file if such a file exists. :return: ``Deferred bytes`` with the tag name applied to the built image. """ if dockerfile_variables is None: dockerfile_variables = {} working_dir = FilePath(self.test.mktemp()) working_dir.makedirs() docker_dir = working_dir.child('docker') shutil.copytree(self.source_dir.path, docker_dir.path) template_file = docker_dir.child('Dockerfile.in') docker_file = docker_dir.child('Dockerfile') if template_file.exists() and not docker_file.exists(): self._process_template( template_file, docker_file, dockerfile_variables) tag = b"flockerlocaltests/" + random_name(self.test).lower() # XXX: This dumps lots of debug output to stderr which messes up the # test results output. It's useful debug info incase of a test failure # so it would be better to send it to the test.log file. See # https://clusterhq.atlassian.net/browse/FLOC-171 command = [ b'docker', b'build', # Always clean up intermediate containers in case of failures. b'--force-rm', b'--tag=%s' % (tag,), docker_dir.path ] d = logged_run_process(reactor, command) if self.cleanup: def remove_image(): client = DockerClient(version="1.15") for container in client.containers(): if container[u"Image"] == tag + ":latest": client.remove_container(container[u"Names"][0]) client.remove_image(tag, force=True) self.test.addCleanup(remove_image) return d.addCallback(lambda ignored: tag)
class MissingTests(TestCase): def setUp(self): self.srcdir = FilePath(self.mktemp()) self.srcdir.makedirs() self.srcdir.child('srca').makedirs() packagedir = self.srcdir.child('srca').child('inctestpkg') packagedir.makedirs() packagedir.child('__init__.py').setContent(b""" from incremental import Version introduced_in = Version('inctestpkg', 'NEXT', 0, 0).short() next_released_version = "inctestpkg NEXT" """) packagedir.child('_version.py').setContent(b""" from incremental import Version __version__ = Version('inctestpkg', 1, 2, 3) __all__ = ["__version__"] """) self.getcwd = lambda: self.srcdir.path self.packagedir = packagedir class Date(object): year = 2016 month = 8 self.date = Date() def test_path(self): """ `incremental.update package --dev` raises and quits if it can't find the package. """ out = [] with self.assertRaises(ValueError): _run(u'inctestpkg', path=None, newversion=None, patch=False, rc=False, dev=True, create=False, _date=self.date, _getcwd=self.getcwd, _print=out.append)
class CreateErrors(SyncTestCase): def setUp(self): super(CreateErrors, self).setUp() self.temp = FilePath(self.mktemp()) self.temp.makedirs() def test_poll_interval(self): with self.assertRaises(usage.UsageError) as ctx: parse_cli("add", "--name", "test", "--author", "test", "--poll-interval=frog", self.temp.path) self.assertEqual(str(ctx.exception), "--poll-interval must be a positive integer") def test_poll_interval_negative(self): with self.assertRaises(usage.UsageError) as ctx: parse_cli("add", "--name", "test", "--author", "test", "--poll-interval=-1", self.temp.path) self.assertEqual(str(ctx.exception), "--poll-interval must be a positive integer") def test_poll_interval_zero(self): with self.assertRaises(usage.UsageError) as ctx: parse_cli("add", "--name", "test", "--author", "test", "--poll-interval=0", self.temp.path) self.assertEqual(str(ctx.exception), "--poll-interval must be a positive integer") def test_scan_interval(self): with self.assertRaises(usage.UsageError) as ctx: parse_cli("add", "--name", "test", "--author", "test", "--scan-interval=frog", self.temp.path) self.assertEqual(str(ctx.exception), "--scan-interval must be a positive integer") def test_scan_interval_negative(self): with self.assertRaises(usage.UsageError) as ctx: parse_cli("add", "--name", "test", "--author", "test", "--scan-interval=-1", self.temp.path) self.assertEqual(str(ctx.exception), "--scan-interval must be a positive integer") def test_scan_interval_zero(self): with self.assertRaises(usage.UsageError) as ctx: parse_cli("add", "--name", "test", "--author", "test", "--scan-interval=0", self.temp.path) self.assertEqual(str(ctx.exception), "--scan-interval must be a positive integer")
def create_client(self): """ Create a new ``FlockerClient`` instance pointing at a running control service REST API. :return: ``FlockerClient`` instance. """ clock = Clock() _, self.port = find_free_port() self.persistence_service = ConfigurationPersistenceService( clock, FilePath(self.mktemp())) self.persistence_service.startService() self.cluster_state_service = ClusterStateService(reactor) self.cluster_state_service.startService() source = ChangeSource() # Prevent nodes being deleted by the state wiper. source.set_last_activity(reactor.seconds()) self.cluster_state_service.apply_changes_from_source( source=source, changes=[ NodeState(uuid=node.uuid, hostname=node.public_address) for node in [self.node_1, self.node_2] ], ) self.addCleanup(self.cluster_state_service.stopService) self.addCleanup(self.persistence_service.stopService) credential_set, _ = get_credential_sets() credentials_path = FilePath(self.mktemp()) credentials_path.makedirs() api_service = create_api_service( self.persistence_service, self.cluster_state_service, TCP4ServerEndpoint(reactor, self.port, interface=b"127.0.0.1"), rest_api_context_factory( credential_set.root.credential.certificate, credential_set.control), # Use consistent fake time for API results: clock) api_service.startService() self.addCleanup(api_service.stopService) credential_set.copy_to(credentials_path, user=True) return FlockerClient(reactor, b"127.0.0.1", self.port, credentials_path.child(b"cluster.crt"), credentials_path.child(b"user.crt"), credentials_path.child(b"user.key"))
def test_get_device_path_correct_with_attached_disk(self): """ get_device_path returns the correct device name even when a non-Cinder volume has been attached. See FLOC-2859. """ instance_id = self.blockdevice_api.compute_instance_id() host_device = "/dev/null" tmpdir = FilePath(self.mktemp()) tmpdir.makedirs() virtio = VirtIOClient.using_insecure_tls(instance_id, tmpdir) virtio.attach_disk(host_device, "vdc") self.addCleanup(virtio.detach_disk, host_device) cinder_volume = self.cinder.create( size=int(Byte(get_minimum_allocatable_size()).to_GiB().value)) CINDER_VOLUME(id=cinder_volume.id).write() self.addCleanup(self._cleanup, instance_id, cinder_volume) volume = wait_for_volume_state(volume_manager=self.cinder, expected_volume=cinder_volume, desired_state=u'available', transient_states=(u'creating', )) devices_before = set(FilePath('/dev').children()) attached_volume = self.nova.create_server_volume( server_id=instance_id, volume_id=volume.id, device=None, ) volume = wait_for_volume_state( volume_manager=self.cinder, expected_volume=attached_volume, desired_state=u'in-use', transient_states=( u'available', u'attaching', ), ) devices_after = set(FilePath('/dev').children()) new_devices = devices_after - devices_before [new_device] = new_devices device_path = self.blockdevice_api.get_device_path(volume.id) self.assertEqual(device_path.realpath(), new_device)
class ControlScriptTests(SynchronousTestCase): """ Tests for ``ControlScript``. """ def setUp(self): """ Create some certificates to use when creating the control service. """ ca_set, _ = get_credential_sets() self.certificate_path = FilePath(self.mktemp()) self.certificate_path.makedirs() ca_set.copy_to(self.certificate_path, control=True) self.script = ControlScript() self.options = ControlOptions() self.data_path = FilePath(self.mktemp()) self.options.parseOptions([ b"--port", b"tcp:8001", b"--agent-port", b"tcp:8002", b"--data-path", self.data_path.path, b"--certificates-directory", self.certificate_path.path ]) def test_no_immediate_stop(self): """ The ``Deferred`` returned from ``ControlScript`` is not fired. """ self.assertNoResult(self.script.main(MemoryCoreReactor(), self.options)) def test_starts_persistence_service(self): """ ``ControlScript.main`` starts a configuration persistence service. """ reactor = MemoryCoreReactor() self.script.main(reactor, self.options) self.assertTrue(self.data_path.isdir()) def test_starts_cluster_state_service(self): """ ``ControlScript.main`` starts a cluster state service. """ reactor = MemoryCoreReactor() self.script.main(reactor, self.options) server = reactor.tcpServers[0] control_resource = server[1].wrappedFactory.resource service = control_resource._v1_user.cluster_state_service self.assertEqual((service.__class__, service.running), (ClusterStateService, True))
def test_childrenNotFound(self): """ Any child resource of L{static.DirectoryLister} renders an HTTP I{NOT FOUND} response code. """ path = FilePath(self.mktemp()) path.makedirs() lister = static.DirectoryLister(path.path) request = self._request('') child = resource.getChildForRequest(lister, request) result = _render(child, request) def cbRendered(ignored): self.assertEquals(request.responseCode, http.NOT_FOUND) result.addCallback(cbRendered) return result
def test_load_error_on_non_existent_key_file(self): """ A ``PathError`` is raised if the key file path given to ``RootCredential.from_path`` does not exist. """ path = FilePath(self.mktemp()) path.makedirs() crt_path = path.child(AUTHORITY_CERTIFICATE_FILENAME) crt_file = crt_path.open(b'w') crt_file.write(b"dummy") crt_file.close() e = self.assertRaises(PathError, RootCredential.from_path, path) expected = ("Unable to load certificate authority file. Please run " "`flocker-ca initialize` to generate a new certificate " "authority. No such file or directory {path}").format( path=path.child(AUTHORITY_KEY_FILENAME).path) self.assertEqual(str(e), expected)
def test_add_with_environment(self): """ ``DockerClient.add`` accepts an environment object whose ID and variables are used when starting a docker image. """ docker_dir = FilePath(self.mktemp()) docker_dir.makedirs() docker_dir.child(b"Dockerfile").setContent( b'FROM busybox\n' b'CMD ["/bin/sh", "-c", ' b'"while true; do env && echo WOOT && sleep 1; done"]') expected_variables = frozenset({ 'key1': 'value1', 'key2': 'value2', }.items()) unit_name = random_name(self) image = DockerImageBuilder(test=self, source_dir=docker_dir) d = image.build() def image_built(image_name): return self.start_container( unit_name=unit_name, image_name=image_name, environment=Environment(variables=expected_variables), ) d.addCallback(image_built) def started(_): output = "" client = dockerpy_client() while True: output += client.logs(self.namespacing_prefix + unit_name) if "WOOT" in output: break assertContainsAll( output, test_case=self, needles=[ '{}={}\n'.format(k, v) for k, v in expected_variables ], ) d.addCallback(started) return d
def test_emptyProjectCalledOut(self): """ If no changes exist for a project, I{NEWS} gains a new section for that project that includes some helpful text about how there were no interesting changes. """ project = FilePath(self.mktemp()).child("twisted") project.makedirs() self.createStructure(project, {'NEWS': self.existingText}) self.builder.build(project, project.child('NEWS'), "Super Awesometastic 32.16") results = project.child('NEWS').getContent() self.assertEqual( results, 'Super Awesometastic 32.16\n' '=========================\n' '\n' + self.builder._NO_CHANGES + '\n\n' + self.existingText)
def build_slow_shutdown_image(self): """ Create a Docker image that takes a while to shut down. This should really use Python instead of shell: https://clusterhq.atlassian.net/browse/FLOC-719 :return: The name of created Docker image. """ path = FilePath(self.mktemp()) path.makedirs() path.child(b"Dockerfile.in").setContent("""\ FROM busybox CMD sh -c "trap \"\" 2; sleep 3" """) image = DockerImageBuilder(test=self, source_dir=path) return image.build()
def build_dummy_image(registry): path = FilePath(self.mktemp()) path.makedirs() path.child(b"Dockerfile.in").setContent(b"FROM busybox\n" b"CMD /bin/true\n") builder = DockerImageBuilder( test=self, source_dir=path, # We're going to manipulate the various tags on the image # ourselves in this test. We'll do (the slightly more # complicated) cleanup so the builder shouldn't (and will # encounter errors if we let it). cleanup=False, ) building = builder.build() building.addCallback(lambda image_name: (image_name, registry)) return building
def postOptions(self): if self.subCommand is None: return self.opt_help() if self["pool"] is None: # TODO untested homePath = FilePath("/var/lib/dvol/volumes") if not homePath.exists(): homePath.makedirs() self["pool"] = homePath.path lockFactory = DockerLock if self["disable-docker-integration"]: # Do not attempt to connect to Docker if we've been asked not to. lockFactory = NullLock self.voluminous = Voluminous(self["pool"], lockFactory=lockFactory) self.subOptions.run(self.voluminous)
def main(): plugins_dir = FilePath("/run/docker/plugins/") if not plugins_dir.exists(): plugins_dir.makedirs() dvol_path = FilePath("/var/lib/dvol/volumes") if not dvol_path.exists(): dvol_path.makedirs() voluminous = Voluminous(dvol_path.path) sock = plugins_dir.child("%s.sock" % (VOLUME_DRIVER_NAME, )) if sock.exists(): sock.remove() adapterServer = internet.UNIXServer(sock.path, getAdapter(voluminous)) reactor.callWhenRunning(adapterServer.startService) reactor.run()
def test_load_error_on_non_existent_key_file(self): """ A ``PathError`` is raised if the key file path given to ``UserCredential.from_path`` does not exist. """ path = FilePath(self.mktemp()) path.makedirs() crt_path = path.child(self.cert_file_name) crt_file = crt_path.open(b'w') crt_file.write(self.credential.credential.certificate.dumpPEM()) crt_file.close() e = self.assertRaises(PathError, cls.from_path, path, **kwargs) expected = ("Private key file could not be opened. " "No such file or directory " "{path}").format( path=path.child(self.key_file_name).path) self.assertEqual(str(e), expected)
def test_saveKeyBadFingerPrintformat(self): """ L{_saveKey} raises C{keys.BadFingerprintFormat} when unsupported formats are requested. """ base = FilePath(self.mktemp()) base.makedirs() filename = base.child('id_rsa').path key = Key.fromString(privateRSA_openssh) with self.assertRaises(BadFingerPrintFormat) as em: _saveKey(key, { 'filename': filename, 'pass': '******', 'format': 'sha-base64' }) self.assertEqual('Unsupported fingerprint format: sha-base64', em.exception.args[0])
def test_pathServer(self): """ The I{--path} option to L{makeService} causes it to return a service which will listen on the server address given by the I{--port} option. """ path = FilePath(self.mktemp()) path.makedirs() port = self.mktemp() options = Options() options.parseOptions(['--port', 'unix:' + port, '--path', path.path]) service = makeService(options) service.startService() self.addCleanup(service.stopService) self.assertIsInstance(service.services[0].factory.resource, File) self.assertEqual(service.services[0].factory.resource.path, path.path) self.assertTrue(os.path.exists(port)) self.assertTrue(stat.S_ISSOCK(os.stat(port).st_mode))
def test_add_with_volumes(self): """ ``DockerClient.add`` accepts a list of ``Volume`` instances which are mounted within the container. """ docker_dir = FilePath(self.mktemp()) docker_dir.makedirs() docker_dir.child(b"Dockerfile").setContent( b'FROM busybox\n' b'CMD ["/bin/sh", "-c", ' b'"touch /mnt1/a; touch /mnt2/b"]') image = DockerImageBuilder(test=self, source_dir=docker_dir) d = image.build() def image_built(image_name): unit_name = random_name(self) path1 = FilePath(self.mktemp()) path1.makedirs() path2 = FilePath(self.mktemp()) path2.makedirs() d = self.start_container( unit_name=unit_name, image_name=image_name, volumes=[ Volume(node_path=path1, container_path=FilePath(b"/mnt1")), Volume(node_path=path2, container_path=FilePath(b"/mnt2")) ], expected_states=(u'inactive', ), ) return d.addCallback(lambda _: (path1, path2)) d.addCallback(image_built) def started((path1, path2)): expected1 = path1.child(b"a") expected2 = path2.child(b"b") for i in range(100): if expected1.exists() and expected2.exists(): return else: time.sleep(0.1) self.fail("Files never created.") return d.addCallback(started)
def test_leave_no_folder(self): """ Create a magic folder and then leave the folder. Leaving it again should result in an error. """ # Get a magic folder. magic_folder = FilePath(self.mktemp()) magic_folder.makedirs() outcome = yield self.cli([ u"add", u"--name", u"foo", u"--author", u"alice", magic_folder.path, ], ) self.assertThat( outcome.succeeded(), Equals(True), ) outcome = yield self.cli([ u"leave", u"--name", u"foo", u"--really-delete-write-capability", ], ) self.assertThat( outcome.succeeded(), Equals(True), ) outcome = yield self.cli([ u"leave", u"--name", u"foo", ], ) self.assertThat( outcome.succeeded(), Equals(False), ) self.assertIn("No such magic-folder 'foo'", outcome.stderr)