예제 #1
0
    def test_get_put_overwrite(self):
        """
        Overwrite existing files.
        """
        dibbler = self.dibbler
        assert dibbler.getNumFiles() == (True, None, 0)

        # Put two files into Dibbler. One in the root directory, and one in a
        # sub-folder.
        files = {'foo': b'foo', 'bar': b'bar'}
        assert dibbler.put(files).ok
        assert dibbler.getNumFiles() == (True, None, len(files))

        # Fetch the two files. Then verify their content.
        ret = dibbler.get(['foo', 'bar'])
        assert ret.ok and ret.data == files

        # Overwrite the content of 'foo'. Then fetch it and verify that it has
        # the new content. Also check that the number of files in the database
        # is still only 2.
        new_file = {'foo': b'test'}
        assert dibbler.put(new_file).ok
        assert dibbler.get(['foo']) == (True, None, new_file)
        assert dibbler.getNumFiles() == (True, None, 2)

        # Send invalid data format.
        assert not dibbler.put({'xy': 'str_instead_of_bytes'}).ok
예제 #2
0
    def test_addTemplate_with_no_fragments(self):
        """
        Add a template that has no fragments. This must still create a
        'meta.json' file (but nothing else).
        """
        # Create a Dibbler instance and flush all data.
        dibbler = self.dibbler
        assert dibbler.getNumFiles() == (True, None, 0)

        # Define a template for this test.
        t_raw = getTemplate('_templateEmpty')

        # Add the template and verify that the database now contains
        # exactly one file.
        ret = dibbler.addTemplate(t_raw)
        assert ret.ok
        assert dibbler.getNumFiles() == (True, None, 1)
        url = ret.data['url_frag']

        # Download the one- and only meta file and verify that it reports an
        # empty 'fragment' list.
        ret = self.dibbler.getFile('{}/meta.json'.format(url))
        assert ret.ok
        ret = json.loads(ret.data.decode('utf8'))
        assert ret['fragments'] == {}
예제 #3
0
    def test_get_put_basic(self):
        """
        Put files into Dibbler and retrieve them.
        """
        dibbler = self.dibbler
        assert dibbler.getNumFiles() == (True, None, 0)

        files = {'foo': b'foo', 'dir/bar': b'bar'}

        # Put two files into dibbler. One is in the root directory and the
        # other in a sub-folder.
        assert dibbler.put(files).ok
        assert dibbler.getNumFiles() == (True, None, len(files))

        # Fetch the two files and verify their content.
        ret = dibbler.get(['foo', 'dir/bar'])
        assert ret.ok and ret.data == files

        # Fetch only one file.
        ret = dibbler.get(['dir/bar'])
        assert ret.ok and ret.data == {'dir/bar': files['dir/bar']}

        # Attempt to fetch a non-existing file. This must not return an error.
        # It must also not return any files.
        ret = dibbler.get(['blah'])
        assert ret.ok and ret.data == {}

        # Request two files. One exists, the other does not.
        ret = dibbler.get(['foo', 'blah'])
        assert ret.ok and ret.data == {'foo': files['foo']}
예제 #4
0
    def test_remove_files_individual(self):
        """
        Create one file, then copy it to another location.
        """
        dibbler = self.dibbler
        assert dibbler.getNumFiles() == (True, None, 0)

        # Attempt to remove a non-existing file. This must succeed but the
        # number of removed files must be zero.
        assert dibbler.remove(['foo']) == (True, None, 0)

        # Add two files, then remove them individually.
        files = {'foo': b'foo', 'bar': b'bar'}
        assert dibbler.put(files).ok
        assert dibbler.getNumFiles() == (True, None, 2)
        assert dibbler.remove(['foo']) == (True, None, 1)
        assert dibbler.getNumFiles() == (True, None, 1)
        assert dibbler.remove(['bar']) == (True, None, 1)
        assert dibbler.getNumFiles() == (True, None, 0)

        # Remove the same file multiple times.
        assert dibbler.put(files).ok
        assert dibbler.getNumFiles() == (True, None, 2)
        assert dibbler.remove(['foo']) == (True, None, 1)
        assert dibbler.getNumFiles() == (True, None, 1)
        assert dibbler.remove(['foo']) == (True, None, 0)
        assert dibbler.getNumFiles() == (True, None, 1)

        # Remove two existing files, plus one non-existing file, with a single
        # call.
        assert dibbler.put(files).ok
        assert dibbler.getNumFiles() == (True, None, 2)
        assert dibbler.remove(['foo', 'bar', 'blah']) == (True, None, 2)
        assert dibbler.getNumFiles() == (True, None, 0)
예제 #5
0
    def test_updateFragments_partial(self):
        """
        Simliar to previous test in the sense that it spawns and updates
        fragments. However, this time some fragments will be removed
        altogether, instead of just being updated.
        """
        dibbler = self.dibbler

        # The original template has the following three fragments:
        frags_orig = {
            'f1': getFragRaw(),
            'f2': getFragDae(),
            'f3': getFragRaw()
        }
        t1 = getTemplate('t1', fragments=frags_orig)

        # The fragment update will use the following data. It translates to
        # keeping the first intact, removing the second, and modifying the
        # fragment type for the third one.
        frags_new = {
            'f2': getFragNone(),
            'f3': getFragDae(),
        }

        # Add the template, spawn one instance, and verify all fragments.
        assert dibbler.addTemplate(t1).ok
        ret = dibbler.spawnTemplate(1, t1.aid)
        assert ret.ok
        self.verifyRaw(ret.data['url_frag'], 'f1', frags_orig)
        self.verifyDae(ret.data['url_frag'], 'f2', frags_orig)
        self.verifyRaw(ret.data['url_frag'], 'f3', frags_orig)

        # Record the current number of files in Dibbler. There must be one
        # 'meta.json', two raw files (one each), 3 Collada files (dae + 2
        # textures). These files exist twice, once in the template store and
        # once in the instance store.
        file_cnt = dibbler.getNumFiles().data
        assert file_cnt == 2 * (1 + 2 * 1 + 1 * 3)

        # Update the fragments: keep first (raw, +0), delete second (dae, -3),
        # convert third from raw to dae (-1 + 3).
        assert dibbler.updateFragments(1, frags_new).ok

        # Record the current number of files in Dibbler.
        assert dibbler.getNumFiles().data == file_cnt + (0) + (-3) + (-1 + 3)

        # Verify that the first fragment is still intact, the second does not
        # exist anymore, and the third was updated.
        self.verifyRaw(ret.data['url_frag'], 'f1', frags_orig)
        with pytest.raises(AssertionError):
            self.verifyDae(ret.data['url_frag'], 'f2', frags_orig)
        self.verifyDae(ret.data['url_frag'], 'f3', frags_new)
예제 #6
0
    def test_addDaeTemplate(self):
        """
        Add a Collada template and fetch the individual files again afterwards.
        """
        dibbler = self.dibbler

        # Define a template for this test.
        frag = {'foo': getFragDae()}
        t_dae = getTemplate('_templateEmpty', fragments=frag)

        # Create a Dibbler instance and flush all data.
        assert dibbler.getNumFiles() == (True, None, 0)

        # Add the first template and verify that the database now contains
        # extactly fourc files (a meta file, the DAE file, and two textures).
        ret = dibbler.addTemplate(t_dae)
        assert dibbler.getNumFiles() == (True, None, 4)

        # Fetch- and verify the model.
        self.verifyDae(ret.data['url_frag'], 'foo', frag)
예제 #7
0
    def test_addRawTemplate(self):
        """
        Add a raw template and fetch the individual files again afterwards.
        """
        # Create a Dibbler instance and flush all data.
        dibbler = self.dibbler
        assert dibbler.getNumFiles() == (True, None, 0)

        # Define a template for this test.
        frags = {'foo': getFragRaw()}
        t_raw = getTemplate('_templateEmpty', fragments=frags)

        # Add the first template and verify that the database now contains
        # exactly two files (a meta file, and the actual fragment data).
        ret = dibbler.addTemplate(t_raw)
        assert ret.ok
        assert dibbler.getNumFiles() == (True, None, 2)

        # Fetch- and verify the model.
        self.verifyRaw(ret.data['url_frag'], 'foo', frags)
예제 #8
0
    def test_spawnTemplate(self):
        """
        Add two templates, then spawn the first one twice and the second
        one once.
        """
        dibbler = self.dibbler

        # Define two templates.
        frag_raw = {'fraw': getFragRaw()}
        frag_dae = {'fdae': getFragDae()}
        t_raw = getTemplate('t_name_raw', fragments=frag_raw)
        t_dae = getTemplate('t_name_dae', fragments=frag_dae)

        # Add the templates and verify there are 6 files in the DB now. The
        # first template has two files (1 meta.json plus 1 for the raw data)
        # and the second has 4 files (1 meta.json plus 3 for the Collada data).
        dibbler.addTemplate(t_raw)
        dibbler.addTemplate(t_dae)
        assert dibbler.getNumFiles() == (True, None, 2 + 4)

        # Spawn some instances.
        ret_1 = dibbler.spawnTemplate(1, t_raw.aid)
        ret_2 = dibbler.spawnTemplate(2, t_raw.aid)
        ret_3 = dibbler.spawnTemplate(3, t_dae.aid)
        assert ret_1.ok and ret_2.ok and ret_3.ok

        # Dibbler must now hold the original 6 files plus an additional 8 files
        # (2x2 for the two Raw instances, and another 4 for the one Collada
        # instance).
        assert dibbler.getNumFiles() == (True, None, (2 + 4) + (2 * 2 + 1 * 4))

        # Verify that all files are correct.
        self.verifyRaw(ret_1.data['url_frag'], 'fraw', frag_raw)
        self.verifyRaw(ret_2.data['url_frag'], 'fraw', frag_raw)
        self.verifyDae(ret_3.data['url_frag'], 'fdae', frag_dae)

        # Attempt to spawn a non-existing template. This must fail and the
        # number of files in Dibbler must not change.
        assert not dibbler.spawnTemplate(10, 'blah').ok
        assert dibbler.getNumFiles() == (True, None, (2 + 4) + (2 * 2 + 1 * 4))
예제 #9
0
    def test_copy_individual(self):
        """
        Create one file, then copy it to another location.
        """
        dibbler = self.dibbler
        assert dibbler.getNumFiles() == (True, None, 0)

        # Put one file into Dibbler.
        assert dibbler.put({'src': b'src'}).ok
        assert dibbler.getNumFiles() == (True, None, 1)

        # Copy the file. Verify their contents match.
        assert dibbler.copy({'src': 'dst'}) == (True, None, 1)
        assert dibbler.getNumFiles() == (True, None, 2)
        ret = dibbler.get(['src', 'dst'])
        assert ret.ok
        assert ret.data == {'src': b'src', 'dst': b'src'}

        # It is permissible to copy a file onto itself.
        assert dibbler.copy({'src': 'src'}).ok
        assert dibbler.getNumFiles() == (True, None, 2)
        assert dibbler.get(['src']) == (True, None, {'src': b'src'})

        # If a non-existing file should be copied then the operation must also
        # succeed, yet nothing must be copied.
        assert dibbler.copy({'blah': 'xyz'}).ok
        assert dibbler.getNumFiles() == (True, None, 2)

        # Copy two files at once. To make the test clearer we will first
        # overwrite the 'dst' file with new content to make it different from
        # 'src'.
        assert dibbler.put({'dst': b'dst'}).ok
        assert dibbler.copy({'src': '/newdir/src', 'dst': '/newdir/dst'})
        ret = dibbler.get(['src', 'dst', '/newdir/src', '/newdir/dst'])
        assert ret.ok and ret.data == {
            'src': b'src',
            'dst': b'dst',
            '/newdir/src': b'src',
            '/newdir/dst': b'dst'
        }
예제 #10
0
    def test_invalid_copy_arguments(self):
        """
        All copy targets must be unique. For instance, the argument
        dibbler.copy({'file1': 'dst', 'file2': dst}) is not allowed because
        both files would be copied to 'dst' and it is not clear which one takes
        precedence.
        """
        dibbler = self.dibbler
        assert dibbler.getNumFiles() == (True, None, 0)

        # Create two files.
        files = {'foo': b'foo', 'bar': b'bar'}
        assert dibbler.put(files).ok

        # Attempt to copy both files to the same target name.
        assert not dibbler.copy({'foo': 'blah', 'bar': 'blah'}).ok
예제 #11
0
    def test_deleteInstance(self):
        """
        Add and remove an instance.
        """
        dibbler = self.dibbler

        # Define two templates.
        frag_raw = {'foo': getFragRaw()}
        frag_dae = {'bar': getFragDae()}
        t_raw = getTemplate('temp_raw', fragments=frag_raw)
        t_dae = getTemplate('temp_dae', fragments=frag_dae)

        # Verify that Dibbler is empty.
        assert dibbler.getNumFiles() == (True, None, 0)

        # Add- and verify a Raw- and Collada template. The raw template 2 files
        # (meta.json plus model.json) whereas the Collada template has 4 files
        # (meta.json plus 1 dae file plus 2 textures).
        ret = dibbler.addTemplate(t_raw)
        assert dibbler.getNumFiles() == (True, None, 2)
        self.verifyRaw(ret.data['url_frag'], 'foo', frag_raw)
        ret = dibbler.addTemplate(t_dae)
        assert dibbler.getNumFiles() == (True, None, 2 + 4)
        self.verifyDae(ret.data['url_frag'], 'bar', frag_dae)

        # Spawn some instances.
        assert dibbler.spawnTemplate(1, 'temp_raw').ok
        assert dibbler.spawnTemplate(2, 'temp_dae').ok
        assert dibbler.spawnTemplate(3, 'temp_raw').ok
        self.verifyRaw('{}/1'.format(config.url_instances), 'foo', frag_raw)
        self.verifyDae('{}/2'.format(config.url_instances), 'bar', frag_dae)
        self.verifyRaw('{}/3'.format(config.url_instances), 'foo', frag_raw)
        base_cnt = (2 + 4) + 2 * 2 + 1 * 4
        assert dibbler.getNumFiles() == (True, None, base_cnt)

        # Remove a non-existing object. This must succeed but Dibbler must not
        # have removed any files.
        assert dibbler.deleteInstance(10) == (True, None, 0)
        assert dibbler.getNumFiles() == (True, None, base_cnt)

        # Remove the first Raw object. This must remove two files and leave the
        # other two instances intact.
        assert dibbler.deleteInstance(1) == (True, None, 2)
        base_cnt -= 2
        assert dibbler.getNumFiles() == (True, None, base_cnt)
        with pytest.raises(AssertionError):
            self.verifyRaw('{}/1'.format(config.url_instances), 'foo', frag_raw)
        self.verifyDae('{}/2'.format(config.url_instances), 'bar', frag_dae)
        self.verifyRaw('{}/3'.format(config.url_instances), 'foo', frag_raw)

        # Remove the same instance again. This must succeed but Dibbler must
        # not remove any files.
        assert dibbler.deleteInstance(1) == (True, None, 0)

        # Remove the Collada instance. This must delete four files (meta.json +
        # dae + 2 textures).
        assert dibbler.deleteInstance(2) == (True, None, 4)
        base_cnt -= 4
        assert dibbler.getNumFiles() == (True, None, base_cnt)
        with pytest.raises(AssertionError):
            self.verifyRaw('{}/1'.format(config.url_instances), 'foo', frag_raw)
        with pytest.raises(AssertionError):
            self.verifyDae('{}/2'.format(config.url_instances), 'bar', frag_dae)
        self.verifyRaw('{}/3'.format(config.url_instances), 'foo', frag_raw)

        # Remove the second Raw instance.
        assert dibbler.deleteInstance(3) == (True, None, 2)
        base_cnt -= 2
        assert dibbler.getNumFiles() == (True, None, base_cnt)
        with pytest.raises(AssertionError):
            self.verifyRaw('{}/1'.format(config.url_instances), 'foo', frag_raw)
        with pytest.raises(AssertionError):
            self.verifyDae('{}/2'.format(config.url_instances), 'bar', frag_dae)
        with pytest.raises(AssertionError):
            self.verifyRaw('{}/3'.format(config.url_instances), 'foo', frag_raw)
예제 #12
0
    def test_deleteTemplate(self):
        """
        Add two templates and then delete them. This functions also tests some
        corner cases where the delete-request is a substring of another
        template.
        """
        dibbler = self.dibbler

        # Define two templates.
        frag_raw = {'foo': getFragRaw()}
        frag_dae = {'bar': getFragDae()}
        t1 = getTemplate('name1', fragments=frag_dae)
        t11 = getTemplate('name11', fragments=frag_raw)

        # Verify that Dibbler's database is pristine.
        assert dibbler.getNumFiles() == (True, None, 0)

        # Add- and verify the Raw template.
        ret = dibbler.addTemplate(t11)
        assert dibbler.getNumFiles() == (True, None, 2)
        self.verifyRaw(ret.data['url_frag'], 'foo', frag_raw)

        # Remove the Raw template and ensure it does not exist anymore.
        assert dibbler.deleteTemplate('name11').ok
        assert dibbler.getNumFiles() == (True, None, 0)
        with pytest.raises(AssertionError):
            self.verifyRaw(ret.data['url_frag'], 'foo', frag_raw)

        # Attempt to remove the Raw template once more. Dibbler must not delete
        # any files, albeit the call itself must succeed.
        assert dibbler.deleteTemplate('blah').ok
        assert dibbler.getNumFiles() == (True, None, 0)

        # Add- and verify the Raw- and Collada templates.
        del ret
        ret_raw = dibbler.addTemplate(t11)
        ret_dae = dibbler.addTemplate(t1)
        assert dibbler.getNumFiles() == (True, None, 6)
        self.verifyRaw(ret_raw.data['url_frag'], 'foo', frag_raw)
        self.verifyDae(ret_dae.data['url_frag'], 'bar', frag_dae)

        # Remove the Collada template whose name is a substring of the first.
        assert dibbler.deleteTemplate('name1') == (True, None, 4)
        assert dibbler.getNumFiles() == (True, None, 2)
        self.verifyRaw(ret_raw.data['url_frag'], 'foo', frag_raw)
        with pytest.raises(AssertionError):
            self.verifyRaw(ret_dae.data['url_frag'], 'bar', frag_dae)

        # Remove the Collada template again. No files must be deleted this
        # time.
        assert dibbler.deleteTemplate('name1') == (True, None, 0)
        assert dibbler.getNumFiles() == (True, None, 2)

        # Attempt to remove a non-existing template. The call must succeed but
        # Dibbler must not delete any files.
        assert dibbler.deleteTemplate('blah') == (True, None, 0)
        assert dibbler.getNumFiles() == (True, None, 2)

        # Delete the one remaining template (Raw template) and verify that
        # Dibbler does not hold any files anymore whatsoever afterwards.
        assert dibbler.deleteTemplate('name11') == (True, None, 2)
        assert dibbler.getNumFiles() == (True, None, 0)
        with pytest.raises(AssertionError):
            self.verifyRaw(ret_raw.data['url_frag'], 'foo', frag_raw)
        with pytest.raises(AssertionError):
            self.verifyRaw(ret_dae.data['url_frag'], 'bar', frag_dae)
예제 #13
0
    def test_remove_directory(self):
        """
        Remove all files with common prefix.
        """
        dibbler = self.dibbler
        assert dibbler.getNumFiles() == (True, None, 0)

        # Create files a small directory hierarchy.
        files = {
            'dir1/foo1': b'foo1',
            'dir1/bar1': b'bar1',
            'dir2/foo2': b'foo2',
            'dir2/bar2': b'bar2',
            'dir2/sub/foo3': b'foo3',
            'dir2/sub/bar3': b'bar3'
        }
        assert dibbler.put(files).ok
        assert dibbler.getNumFiles() == (True, None, len(files))

        # Attempt to remove a non-existing directory. The call must succeed yet
        # nothing must have been deleted.
        assert dibbler.removeDirs(['blah']) == (True, None, 0)
        assert dibbler.getNumFiles() == (True, None, len(files))

        # Attempt to remove all files in the non-existent 'dir' directory (not
        # that this is a prefix for the 'dir1/' and 'dir2' directories, and
        # Dibbler must ensure that these are _not_ deleted.
        assert dibbler.removeDirs(['dir']) == (True, None, 0)
        assert dibbler.getNumFiles() == (True, None, len(files))

        # Delete all files in dir1. Then verify the number of files.
        assert dibbler.removeDirs(['dir1']) == (True, None, 2)
        assert dibbler.getNumFiles() == (True, None, len(files) - 2)

        # Delete all files in dir2. Then verify that there are no more files
        # left.
        assert dibbler.removeDirs(['dir2']) == (True, None, 4)
        assert dibbler.getNumFiles() == (True, None, 0)

        # Populate the database again.
        assert dibbler.put(files).ok
        assert dibbler.getNumFiles() == (True, None, len(files))

        # Delete 'dir2/sub'.
        assert dibbler.removeDirs(['dir2/sub']) == (True, None, 2)
        assert dibbler.getNumFiles() == (True, None, len(files) - 2)
        fnames = ['dir1/foo1', 'dir1/bar1', 'dir2/foo2', 'dir2/bar2']
        ret = dibbler.get(fnames)
        assert ret.ok
        for fname in fnames:
            ret.data[fname] == files[fname]

        # Reset the database and populate it again.
        self.dibbler.reset()
        assert dibbler.put(files).ok
        assert dibbler.getNumFiles() == (True, None, len(files))

        # As before, delete the 'dir2/sub' directory, but this time supply a
        # trailing a slash. The result must be the same.
        assert dibbler.removeDirs(['dir2/sub/']) == (True, None, 2)
        assert dibbler.getNumFiles() == (True, None, len(files) - 2)
        fnames = ['dir1/foo1', 'dir1/bar1', 'dir2/foo2', 'dir2/bar2']
        ret = dibbler.get(fnames)
        assert ret.ok
        for fname in fnames:
            ret.data[fname] == files[fname]