예제 #1
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)
예제 #2
0
    def test_Template(self):
        # Define boosters and factories.
        boosters = {
            "0": Booster(pos=(0, 1, 2), direction=(1, 0, 0), minval=0, maxval=1, force=0),
            "1": Booster(pos=(3, 4, 5), direction=(0, 1, 0), minval=0, maxval=2, force=0),
        }
        factories = {
            "0": Factory(pos=(0, 1, 2), direction=(0, 0, 1), templateID="_templateBox", exit_speed=(0, 1)),
            "1": Factory(pos=(3, 4, 5), direction=(0, 1, 0), templateID="_templateBox", exit_speed=(0, 1)),
        }

        rbs = getRigidBody(position=(1, 2, 3))

        # Define a new template with two boosters and add it to Azrael.
        temp_t = getTemplate(
            "t1", rbs=rbs, fragments={"1": getFragRaw(), "2": getFragDae()}, boosters=boosters, factories=factories
        )

        # Verify that it is JSON compatible.
        assert self.isJsonCompatible(temp_t, Template)

        # Verify that Template._asdict() method calls the _asdict() methods
        # for all collision shapes, fragments, boosters, and factories.
        temp_d = temp_t._asdict()
        fragments_d = {k: v._asdict() for (k, v) in temp_t.fragments.items()}
        boosters_d = {k: v._asdict() for (k, v) in temp_t.boosters.items()}
        factories_d = {k: v._asdict() for (k, v) in temp_t.factories.items()}
        rbs_d = rbs._asdict()
        assert temp_d["fragments"] == fragments_d
        assert temp_d["boosters"] == boosters_d
        assert temp_d["factories"] == factories_d
        assert temp_d["rbs"] == rbs_d
예제 #3
0
    def getTestTemplate(self, templateID='templateID'):
        """
        Return a valid template with non-trivial data. The template contains
        multiple fragments (Raw and Collada), boosters, factories, and a rigid
        body.

        This is a convenience method only.
        """
        # Define a new object with two boosters and one factory unit.
        # The 'boosters' and 'factories' arguments are a list of named
        # tuples. Their first argument is the unit ID (Azrael does not
        # automatically assign any IDs).
        boosters = {
            '0': aztypes.Booster(position=(0, 1, 2), direction=(0, 0, 1), force=0),
            '1': aztypes.Booster(position=(6, 7, 8), direction=(0, 1, 0), force=0),
        }
        factories = {
            '0': aztypes.Factory(position=(0, 0, 0), direction=(0, 0, 1),
                                 templateID='_templateBox',
                                 exit_speed=(0.1, 0.5))
        }

        # Create some fragments...
        frags = {'f1': getFragRaw(), 'f2': getFragDae()}

        # ... and a body...
        body = getRigidBody(position=(1, 2, 3))

        # ... then compile and return the template.
        return azrael.test.test.getTemplate(
            templateID,
            rbs=body,
            fragments=frags,
            boosters=boosters,
            factories=factories)
예제 #4
0
    def test_deleteInstance(self):
        """
        Add/remove an instance from Dibbler via Clerk and verify via WebServer.
        """
        self.dibbler.reset()
        azrael.datastore.init(flush=True)
        clerk = azrael.clerk.Clerk()

        # Create a Template.
        frags = {'name1': getFragRaw()}
        t1 = getTemplate('t1', fragments=frags)

        # Add-, spawn-, and verify the template.
        assert clerk.addTemplates([t1]).ok
        self.verifyTemplate('{}/t1'.format(config.url_templates), t1.fragments)
        ret = clerk.spawn([{'templateID': 't1', 'rbs': {'imass': 1}}])
        assert ret.data == ['1']

        # Verify that the instance exists.
        url_inst = config.url_instances
        self.verifyTemplate('{}/{}'.format(url_inst, 1), frags)

        # Delete the instance and verify it is now gone.
        cnt = self.dibbler.getNumFiles().data
        assert clerk.removeObjects(['1']) == (True, None, None)
        self.dibbler.getNumFiles().data == cnt - 2
        with pytest.raises(AssertionError):
            self.verifyTemplate('{}/{}'.format(url_inst, 1), frags)
예제 #5
0
    def test_Template(self):
        # Define boosters and factories.
        boosters = {
            '0': Booster(position=(0, 1, 2), direction=(1, 0, 0), force=0),
            '1': Booster(position=(3, 4, 5), direction=(0, 1, 0), force=0)
        }
        factories = {
            '0': Factory(position=(0, 1, 2), direction=(0, 0, 1),
                         templateID='_templateBox', exit_speed=(0, 1)),
            '1': Factory(position=(3, 4, 5), direction=(0, 1, 0),
                         templateID='_templateBox', exit_speed=(0, 1))
        }

        rbs = getRigidBody(position=(1, 2, 3))

        # Define a new template with two boosters and add it to Azrael.
        frags = {'1': getFragRaw(), '2': getFragDae()}
        temp_t = getTemplate('t1',
                             rbs=rbs,
                             fragments=frags,
                             boosters=boosters,
                             factories=factories)

        # Verify that Template._asdict() method calls the _asdict() methods
        # for all collision shapes, fragments, boosters, and factories.
        temp_d = temp_t._asdict()
        fragments_d = {k: v._asdict() for (k, v) in temp_t.fragments.items()}
        boosters_d = {k: v._asdict() for (k, v) in temp_t.boosters.items()}
        factories_d = {k: v._asdict() for (k, v)in temp_t.factories.items()}
        rbs_d = rbs._asdict()
        assert temp_d['fragments'] == fragments_d
        assert temp_d['boosters'] == boosters_d
        assert temp_d['factories'] == factories_d
        assert temp_d['rbs'] == rbs_d
예제 #6
0
    def test_remove_fragments(self, client_type):
        """
        Remove a fragment. This test is basically the integration test for
        'test_dibbler.test_updateFragments_partial'.
        """
        # Get the client for this test.
        client = self.clients[client_type]

        # Convenience.
        objID = 1

        # The original template has the following three fragments:
        frags_orig = {
            'fname_1': getFragRaw(),
            'fname_2': getFragDae(),
            'fname_3': getFragRaw(),
        }
        t1 = getTemplate('t1', fragments=frags_orig)

        # Add a new template and spawn it.
        assert client.addTemplates([t1]).ok
        new_obj = {'templateID': t1.aid,
                   'rbs': {'position': (1, 1, 1), 'velocityLin': (-1, -1, -1)}}
        assert client.spawn([new_obj]) == (True, None, [objID])

        # Query the fragment geometries and Body State to verify that both
        # report three fragments.
        ret = client.getFragments([objID])
        assert ret.ok and len(ret.data[objID]) == 3
        ret = client.getObjectStates(objID)
        assert ret.ok and len(ret.data[objID]['frag']) == 3

        # Update the fragments as follows: keep the first intact, remove the
        # second, and modify the third one.
        frags_new = {
            'fname_2': getFragNone()._asdict(),
            'fname_3': getFragDae()._asdict()
        }
        assert client.setFragments({objID: frags_new}).ok

        # After the last update there must now only be two fragments.
        ret = client.getFragments([objID])
        assert ret.ok and len(ret.data[objID]) == 2
        ret = client.getObjectStates(objID)
        assert ret.ok and len(ret.data[objID]['frag']) == 2
예제 #7
0
    def test_spawnTemplates(self):
        """
        Spawn a template and verify it is available via WebServer.
        """
        self.dibbler.reset()
        azrael.datastore.init(flush=True)
        clerk = azrael.clerk.Clerk()

        # # Create two Templates. The first has only one Raw- and two
        # # Collada geometries, the other has it the other way around.
        frags_t1 = {'raw1': getFragRaw(),
                    'dae2': getFragDae(),
                    'dae3': getFragDae()}
        frags_t2 = {'raw4': getFragRaw(),
                    'raw5': getFragRaw(),
                    'dae6': getFragDae()}
        body_t1 = getRigidBody(cshapes={'cssphere': getCSSphere()})
        body_t2 = getRigidBody(cshapes={'csbox': getCSBox()})
        t1 = getTemplate('t1', rbs=body_t1, fragments=frags_t1)
        t2 = getTemplate('t2', rbs=body_t2, fragments=frags_t2)
        del frags_t1, frags_t2

        # Add both templates and verify they are available.
        assert clerk.addTemplates([t1, t2]).ok
        self.verifyTemplate('{}/t1'.format(config.url_templates), t1.fragments)
        self.verifyTemplate('{}/t2'.format(config.url_templates), t2.fragments)

        # No object instance with ID=1 must exist yet.
        url_inst = config.url_instances
        with pytest.raises(AssertionError):
            self.verifyTemplate('{}/{}'.format(url_inst, 1), t1.fragments)

        # Spawn the first template (it must get objID=1).
        ret = clerk.spawn([{'templateID': 't1', 'rbs': {'imass': 1}}])
        assert ret.data == ['1']
        self.verifyTemplate('{}/{}'.format(url_inst, 1), t1.fragments)

        # Spawn two more templates and very their instance models.
        new_objs = [{'templateID': 't2', 'rbs': {'imass': 1}},
                    {'templateID': 't1', 'rbs': {'imass': 1}}]
        ret = clerk.spawn(new_objs)
        assert ret.data == ['2', '3']
        self.verifyTemplate('{}/{}'.format(url_inst, 2), t2.fragments)
        self.verifyTemplate('{}/{}'.format(url_inst, 3), t1.fragments)
예제 #8
0
    def test_setFragments_dae(self, client_type):
        """
        Spawn a new object and modify its geometry at runtime.
        """
        # Get the client for this test.
        client = self.clients[client_type]

        # Get a Collada fragment.
        f_dae = {'f_dae': getFragDae()}

        # Add a new template and spawn it.
        temp = getTemplate('t1', fragments=f_dae)
        assert client.addTemplates([temp]).ok

        new_obj = {'templateID': temp.aid,
                   'rbs': {'position': (1, 1, 1), 'velocityLin': (-1, -1, -1)}}
        ret = client.spawn([new_obj])
        objID = ret.data[0]
        assert ret.ok and ret.data == [objID]
        del temp, new_obj, ret

        # Query the body states to obtain the 'version' value.
        ret = client.getRigidBodies(objID)
        assert ret.ok
        version = ret.data[objID]['rbs'].version

        # Fetch-, modify-, update- and verify the geometry.
        ret = client.getFragments([objID])
        assert ret.ok
        assert ret.data[objID]['f_dae']['fragtype'] == 'DAE'

        # Change the geometry for fragment 'f_dae' to a RAW type.
        assert client.setFragments({objID: {'f_dae': getFragRaw()._asdict()}}).ok

        # Ensure the fragment is now indeed of type 'RAW'.
        ret = client.getFragments([objID])
        assert ret.ok
        assert ret.data[objID]['f_dae']['fragtype'] == 'RAW'

        # Ensure 'version' is different as well.
        ret = client.getRigidBodies(objID)
        assert ret.ok and (ret.data[objID]['rbs'].version != version)

        # Change the fragment geometry once more.
        version = ret.data[objID]['rbs'].version
        assert client.setFragments({objID: {'f_dae': getFragDae()._asdict()}}).ok

        # Ensure it now has type 'DAE' again.
        ret = client.getFragments([objID])
        assert ret.ok
        assert ret.data[objID]['f_dae']['fragtype'] == 'DAE'

        # Ensure 'version' is different as well.
        ret = client.getRigidBodies(objID)
        assert ret.ok and (ret.data[objID]['rbs'].version != version)
예제 #9
0
    def test_updateFragments(self):
        """
        Modify the fragments of a spawned object.
        """
        self.dibbler.reset()
        azrael.database.init()
        clerk = azrael.clerk.Clerk()

        # Create two Templates. The first has only one Raw- and two
        # Collada geometries, the other has it the other way around.
        frags_old = {'name1': getFragRaw(),
                     'name2': getFragDae(),
                     'name3': getFragDae()}
        frags_new = {'name1': getFragDae(),
                     'name2': getFragDae(),
                     'name3': getFragRaw()}
        t1 = getTemplate('t1', fragments=frags_old)

        # Add-, spawn-, and verify the template.
        assert clerk.addTemplates([t1]).ok
        self.verifyTemplate('{}/t1'.format(config.url_templates), t1.fragments)
        ret = clerk.spawn([{'templateID': 't1', 'rbs': {'imass': 1}}])
        objID = 1
        assert ret.data == (objID, )

        # Verify that the instance has the old fragments, not the new ones.
        url_inst = config.url_instances
        self.verifyTemplate('{}/{}'.format(url_inst, 1), frags_old)
        with pytest.raises(AssertionError):
            self.verifyTemplate('{}/{}'.format(url_inst, 1), frags_new)

        # Update the fragments.
        tmp = {k: v._asdict() for (k, v) in frags_new.items()}
        clerk.setFragments({objID: tmp})

        # Verify that the instance now has the new fragments, but not the old
        # ones anymore.
        self.verifyTemplate('{}/{}'.format(url_inst, 1), frags_new)
        with pytest.raises(AssertionError):
            self.verifyTemplate('{}/{}'.format(url_inst, 1), frags_old)
예제 #10
0
    def test_updateFragments_all(self):
        """
        Spawn a template and update all its fragments.
        """
        dibbler = self.dibbler

        # The original template has two fragments, and we will update one of
        # them.
        frags_orig = {'o1': getFragRaw(),
                      'o2': getFragDae()}
        frags_new = {'o1': getFragDae()}
        t1 = getTemplate('t1', fragments=frags_orig)

        # Add the template and spawn two instances.
        assert dibbler.addTemplate(t1).ok
        ret_11 = dibbler.spawnTemplate(11, t1.aid)
        ret_2 = dibbler.spawnTemplate(2, t1.aid)
        assert ret_11.ok and ret_2.ok

        self.verifyRaw(ret_11.data['url_frag'], 'o1', frags_orig)
        self.verifyDae(ret_11.data['url_frag'], 'o2', frags_orig)
        self.verifyRaw(ret_2.data['url_frag'], 'o1', frags_orig)
        self.verifyDae(ret_2.data['url_frag'], 'o2', frags_orig)

        # Attempt to change the fragment of a non-existing object.
        assert not dibbler.updateFragments(20, frags_new).ok

        # Attempt to change the fragment of another non-existing object, but
        # the object ID of this one is '1', which means it is available at
        # '/somewhere/1/...'. However, an object at '/somewhere/11/...' already
        # exists, and without the trailing '/' the first would be a sub-string
        # of the latter. The update method must therefore take care to properly
        # test for existence, especially since directories, internally, do not
        # have a trailing '/'.
        assert not dibbler.updateFragments(1, frags_new).ok

        # The previous attempts to modify fragments of non-existing objectst
        # must not have modified the fragments.
        self.verifyRaw(ret_11.data['url_frag'], 'o1', frags_orig)
        self.verifyDae(ret_11.data['url_frag'], 'o2', frags_orig)
        self.verifyRaw(ret_2.data['url_frag'], 'o1', frags_orig)
        self.verifyDae(ret_2.data['url_frag'], 'o2', frags_orig)

        # Change the first fragments of the first object.
        assert dibbler.updateFragments(11, frags_new).ok

        # Verify that only the first fragment of the '11' object has changed.
        self.verifyDae(ret_11.data['url_frag'], 'o1', frags_new)
        self.verifyDae(ret_11.data['url_frag'], 'o2', frags_orig)
        self.verifyRaw(ret_2.data['url_frag'], 'o1', frags_orig)
        self.verifyDae(ret_2.data['url_frag'], 'o2', frags_orig)
예제 #11
0
    def test_addTemplates(self):
        """
        Add and query a template with one Raw fragment.
        """
        self.dibbler.reset()
        azrael.datastore.init(flush=True)
        clerk = azrael.clerk.Clerk()

        # Create two Templates. The first has only one Raw- and two
        # Collada geometries, the other has it the other way around.
        frags_t1 = {'foo1': getFragRaw(),
                    'bar2': getFragDae(),
                    'bar3': getFragDae()}
        frags_t2 = {'foo4': getFragRaw(),
                    'foo5': getFragRaw(),
                    'bar6': getFragDae()}
        body_a = getRigidBody(cshapes={'cssphere': getCSSphere()})
        body_b = getRigidBody(cshapes={'csbox': getCSBox()})
        t1 = getTemplate('t1', rbs=body_a, fragments=frags_t1)
        t2 = getTemplate('t2', rbs=body_b, fragments=frags_t2)
        del frags_t1, frags_t2

        # Add the first template.
        assert clerk.addTemplates([t1]) == (True, None, {'t1': True})

        # Attempt to add the same template a second time. This must not do
        # anything.
        assert clerk.addTemplates([t1]) == (True, None, {'t1': False})

        # Verify the first template is available for download via WebServer.
        url_template = config.url_templates
        self.verifyTemplate('{}/t1'.format(url_template), t1.fragments)

        # Add the second template and verify both are available for download
        # via WebServer.
        assert clerk.addTemplates([t2]).ok
        self.verifyTemplate('{}/t1'.format(url_template), t1.fragments)
        self.verifyTemplate('{}/t2'.format(url_template), t2.fragments)
예제 #12
0
    def test_FragMeta(self):
        for Getter in (getFragRaw, getFragDae, getFragNone):
            # Get a proper FragMeta, and a stunted one where the 'fragdata'
            # field is None. This case often happens internally in Azrael
            # because the meta data is stored in a separate database.
            frag_a = Getter()
            frag_b = frag_a._replace(fragdata=None)
            assert self.isJsonCompatible(frag_a, FragMeta)
            assert self.isJsonCompatible(frag_b, FragMeta)

        # Verify that 'FragMeta._asdict' also converts the 'fragdata' field
        # to dictionaries.
        frag_t = getFragRaw()
        frag_d = frag_t._asdict()
        assert isinstance(frag_d, dict)
        tmp = frag_t.fragdata._asdict()
        assert isinstance(tmp, dict)
        assert tmp == frag_d["fragdata"]
예제 #13
0
    def setup_method(self, method):
        # Reset the database.
        azrael.database.init()

        # Flush the model database.
        self.dibbler.reset()

        # Insert default objects. None of them has an actual geometry but
        # their collision shapes are: none, sphere, box.
        clerk = azrael.clerk.Clerk()

        frag = {'NoName': getFragRaw()}
        rbs_empty = getRigidBody(cshapes={'csempty': getCSEmpty()})
        rbs_sphere = getRigidBody(cshapes={'cssphere': getCSSphere()})
        rbs_box = getRigidBody(cshapes={'csbox': getCSBox()})
        t1 = getTemplate('_templateEmpty', rbs=rbs_empty, fragments=frag)
        t2 = getTemplate('_templateSphere', rbs=rbs_sphere, fragments=frag)
        t3 = getTemplate('_templateBox', rbs=rbs_box, fragments=frag)
        ret = clerk.addTemplates([t1, t2, t3])
        assert ret.ok
예제 #14
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)
예제 #15
0
    def test_Template(self):
        # Define boosters and factories.
        boosters = {
            '0': Booster(position=(0, 1, 2), direction=(1, 0, 0), force=0),
            '1': Booster(position=(3, 4, 5), direction=(0, 1, 0), force=0)
        }
        factories = {
            '0':
            Factory(position=(0, 1, 2),
                    direction=(0, 0, 1),
                    templateID='_templateBox',
                    exit_speed=(0, 1)),
            '1':
            Factory(position=(3, 4, 5),
                    direction=(0, 1, 0),
                    templateID='_templateBox',
                    exit_speed=(0, 1))
        }

        rbs = getRigidBody(position=(1, 2, 3))

        # Define a new template with two boosters and add it to Azrael.
        frags = {'1': getFragRaw(), '2': getFragDae()}
        temp_t = getTemplate('t1',
                             rbs=rbs,
                             fragments=frags,
                             boosters=boosters,
                             factories=factories)

        # Verify that Template._asdict() method calls the _asdict() methods
        # for all collision shapes, fragments, boosters, and factories.
        temp_d = temp_t._asdict()
        fragments_d = {k: v._asdict() for (k, v) in temp_t.fragments.items()}
        boosters_d = {k: v._asdict() for (k, v) in temp_t.boosters.items()}
        factories_d = {k: v._asdict() for (k, v) in temp_t.factories.items()}
        rbs_d = rbs._asdict()
        assert temp_d['fragments'] == fragments_d
        assert temp_d['boosters'] == boosters_d
        assert temp_d['factories'] == factories_d
        assert temp_d['rbs'] == rbs_d
예제 #16
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))
예제 #17
0
    def test_update_FragmentStates(self, client_type):
        """
        Query and modify fragment states.
        Note that fragment states are updated via 'setFragments'.
        """
        # Get the client for this test.
        client = self.clients[client_type]

        # Convenience.
        objID = 1

        # Add a new template and spawn it.
        temp = getTemplate('t1', fragments={'bar': getFragRaw()})
        assert client.addTemplates([temp]).ok

        new_obj = {'templateID': temp.aid,
                   'rbs': {'position': (1, 1, 1), 'velocityLin': (-1, -1, -1)}}
        ret = client.spawn([new_obj])
        assert ret.ok and ret.data == [objID]
        del temp, new_obj, ret

        # Query the Body State to get the Fragment States. Then verify the
        # Fragment State named 'bar'.
        ret = client.getObjectStates(objID)
        ref = {'bar': {'scale': 1, 'position': [0, 0, 0], 'rotation': [0, 0, 0, 1]}}
        assert ret.ok
        assert ret.data[objID]['frag'] == ref

        # Modify and update the fragment states in Azrael, then query and
        # verify it worked.
        newStates = {objID: {'bar': {'scale': 2.2, 'position': [1, 2, 3],
                                     'rotation': [1, 0, 0, 0]}}}
        assert client.setFragments(newStates).ok
        ret = client.getObjectStates(objID)
        assert ret.ok
        ret = ret.data[objID]['frag']['bar']
        assert ret == newStates[objID]['bar']
예제 #18
0
    def test_create_fetch_template(self, client_type):
        """
        Add a new object to the templateID DB and query it again.
        """
        # Get the client for this test.
        client = self.clients[client_type]

        # Request an invalid ID.
        assert not client.getTemplates(['blah']).ok

        # Clerk has default objects. This one has an empty collision shape...
        name_1 = '_templateEmpty'
        ret = client.getTemplates([name_1])
        assert ret.ok and (len(ret.data) == 1)
        assert ret.data[name_1]['template'].rbs.cshapes == {'csempty': getCSEmpty()}

        # ... this one is a sphere...
        name_2 = '_templateSphere'
        ret = client.getTemplates([name_2])
        assert ret.ok and (len(ret.data) == 1)
        assert ret.data[name_2]['template'].rbs.cshapes == {'cssphere': getCSSphere()}

        # ... and this one is a box.
        name_3 = '_templateBox'
        ret = client.getTemplates([name_3])
        assert ret.ok and (len(ret.data) == 1)
        assert ret.data[name_3]['template'].rbs.cshapes == {'csbox': getCSBox()}

        # Retrieve all three again but with a single call.
        ret = client.getTemplates([name_1, name_2, name_3])
        assert ret.ok
        assert set(ret.data.keys()) == set((name_1, name_2, name_3))
        assert ret.data[name_2]['template'].rbs.cshapes == {'cssphere': getCSSphere()}
        assert ret.data[name_3]['template'].rbs.cshapes == {'csbox': getCSBox()}
        assert ret.data[name_1]['template'].rbs.cshapes == {'csempty': getCSEmpty()}

        # Add a new object template.
        frag = {'bar': getFragRaw()}
        body = getRigidBody()
        temp_name = 't1'
        temp_orig = getTemplate(temp_name, rbs=body, fragments=frag)
        assert client.addTemplates([temp_orig]).ok

        # Fetch the just added template again and verify its content (skip the
        # geometry because it contains only meta information and will be
        # checked afterwards).
        ret = client.getTemplates([temp_name])
        assert ret.ok and (len(ret.data) == 1)
        temp_out = ret.data[temp_name]['template']
        assert temp_out.boosters == temp_orig.boosters
        assert temp_out.factories == temp_orig.factories
        assert temp_out.rbs == temp_orig.rbs

        # Fetch the geometry from the web server and verify it.
        ret = client.getTemplateGeometry(ret.data[temp_name])
        assert ret.ok
        assert ret.data['bar'] == frag['bar'].fragdata
        del ret, temp_out, temp_orig

        # Define a new object with two boosters and one factory unit.
        # The 'boosters' and 'factories' arguments are a list of named
        # tuples. Their first argument is the unit ID (Azrael does not
        # automatically assign any).
        boosters = {
            '0': types.Booster(pos=(0, 0, 0), direction=(0, 0, 1),
                               minval=0, maxval=0.5, force=0),
            '1': types.Booster(pos=(0, 0, 0), direction=(0, 0, 1),
                               minval=0, maxval=0.5, force=0),
        }
        factories = {
            '0': types.Factory(pos=(0, 0, 0), direction=(0, 0, 1),
                               templateID='_templateBox',
                               exit_speed=(0.1, 0.5))
        }

        # Attempt to query the geometry of a non-existing object.
        assert client.getFragments([1]) == (True, None, {1: None})

        # Define a new template, add it to Azrael, spawn it, and record its
        # object ID.
        body = getRigidBody(cshapes={'csbox': getCSBox()})
        temp = getTemplate('t2',
                           rbs=body,
                           fragments=frag,
                           boosters=boosters,
                           factories=factories)
        assert client.addTemplates([temp]).ok
        init = {'templateID': temp.aid,
                'rbs': {'position': (0, 0, 0)}}
        ret = client.spawn([init])
        assert ret.ok and len(ret.data) == 1
        objID = ret.data[0]

        # Retrieve- and verify the geometry of the just spawned object.
        ret = client.getFragments([objID])
        assert ret.ok
        assert ret.data[objID]['bar']['fragtype'] == 'RAW'

        # Retrieve the entire template and verify the CS and geometry, and
        # number of boosters/factories.
        ret = client.getTemplates([temp.aid])
        assert ret.ok and (len(ret.data) == 1)
        t_data = ret.data[temp.aid]['template']
        assert t_data.rbs == body
        assert t_data.boosters == temp.boosters
        assert t_data.factories == temp.factories

        # Fetch the geometry from the Web server and verify it is correct.
        ret = client.getTemplateGeometry(ret.data[temp.aid])
        assert ret.ok
        assert ret.data['bar'] == frag['bar'].fragdata
예제 #19
0
 def test_FragMeta(self):
     # Verify that 'FragMeta._asdict' convert to a dictionary.
     frag_t = getFragRaw()
     frag_d = frag_t._asdict()
     assert isinstance(frag_d, dict)
예제 #20
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)
예제 #21
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)
예제 #22
0
 def test_FragMeta(self):
     # Verify that 'FragMeta._asdict' convert to a dictionary.
     frag_t = getFragRaw()
     frag_d = frag_t._asdict()
     assert isinstance(frag_d, dict)
예제 #23
0
    def test_setFragments_raw(self, client_type):
        """
        Spawn a new object and modify its geometry at runtime.
        """
        # Get the client for this test.
        client = self.clients[client_type]

        # Convenience.
        objID = 1

        # Add a new template and spawn it.
        frag = {'bar': getFragRaw()}
        temp = getTemplate('t1', fragments=frag)
        assert client.addTemplates([temp]).ok

        new_obj = {'templateID': temp.aid,
                   'rbs': {'position': (1, 1, 1),
                           'velocityLin': (-1, -1, -1)}}
        ret = client.spawn([new_obj])
        assert ret.ok and ret.data == [objID]
        del temp, new_obj, ret

        # Query the SV to obtain the 'version' value.
        ret = client.getRigidBodies(objID)
        assert ret.ok
        version = ret.data[objID]['rbs'].version

        # Fetch-, modify-, update- and verify the geometry.
        ret = client.getFragments([objID])
        assert ret.ok
        assert ret.data[objID]['bar']['fragtype'] == 'RAW'

        # Download the fragment.
        base_url = 'http://{ip}:{port}'.format(
            ip=config.addr_webserver, port=config.port_webserver)
        url = base_url + ret.data[objID]['bar']['url_frag'] + '/model.json'
        for ii in range(10):
            assert ii < 8
            try:
                tmp = urllib.request.urlopen(url).readall()
                break
            except urllib.request.URLError:
                time.sleep(0.2)
        tmp = json.loads(tmp.decode('utf8'))
        assert FragRaw(**tmp) == frag['bar'].fragdata

        # Change the fragment geometries.
        cmd = {objID: {k: v._asdict() for (k, v) in frag.items()}}
        assert client.setFragments(cmd).ok

        ret = client.getFragments([objID])
        assert ret.ok
        assert ret.data[objID]['bar']['fragtype'] == 'RAW'

        # Download the fragment.
        url = base_url + ret.data[objID]['bar']['url_frag'] + '/model.json'
        tmp = urllib.request.urlopen(url).readall()
        tmp = json.loads(tmp.decode('utf8'))
        assert FragRaw(**tmp) == frag['bar'].fragdata

        # Ensure 'version' is different as well.
        ret = client.getRigidBodies(objID)
        assert ret.ok and (ret.data[objID]['rbs'].version != version)