Best Python code snippet using tempest_python
test_object_manager.py
Source:test_object_manager.py  
...104            )105        )106        # Run through (de)serializer to fill in any missing vars107        return self.deserializer.deserialize(self.serializer.serialize(msg))108    def _create_object(self, local_id=None, full_id=None, parent_id=None, pos=None, rot=None,109                       pcode=None, namevalue=None, region_handle=None) -> Object:110        msg = self._create_object_update(111            local_id=local_id, full_id=full_id, parent_id=parent_id, pos=pos, rot=rot,112            pcode=pcode, namevalue=namevalue, region_handle=region_handle)113        self.message_handler.handle(msg)114        actual_handle = msg["RegionData"]["RegionHandle"]115        region = self.session.region_by_handle(actual_handle)116        return region.objects.lookup_fullid(msg["ObjectData"]["FullID"])117    def _create_kill_object(self, local_id) -> Message:118        return Message(119            "KillObject",120            Block(121                "ObjectData",122                ID=local_id,123            )124        )125    def _kill_object(self, local_id: int):126        self.message_handler.handle(self._create_kill_object(local_id))127    def _create_object_update_cached(self, local_id: int, region_handle: int = 123,128                                     crc: int = 22, flags: int = 4321):129        return Message(130            'ObjectUpdateCached',131            Block("RegionData", TimeDilation=102, RegionHandle=region_handle),132            Block(133                "ObjectData",134                ID=local_id,135                CRC=crc,136                UpdateFlags=flags,137            )138        )139    def _get_avatar_positions(self) -> Dict[UUID, Vector3]:140        return {av.FullID: av.RegionPosition for av in self.region_object_manager.all_avatars}141class RegionObjectManagerTests(ObjectManagerTestMixin, unittest.IsolatedAsyncioTestCase):142    def test_basic_tracking(self):143        """Does creating an object result in it being tracked?"""144        msg = self._create_object_update()145        self.message_handler.handle(msg)146        obj = self.region_object_manager.lookup_fullid(msg["ObjectData"]["FullID"])147        self.assertIsNotNone(obj)148    def test_terse_object_update(self):149        msg = self._create_object_update(pos=Vector3(1, 2, 3))150        self.message_handler.handle(msg)151        local_id = msg["ObjectData"]["ID"]152        msg = Message(153            'ImprovedTerseObjectUpdate',154            Block('RegionData', RegionHandle=123, TimeDilation=65345),155            Block(156                'ObjectData',157                Data_={158                    'ID': local_id,159                    'State': 0,160                    'FootCollisionPlane': None,161                    'Position': Vector3(-2, -3, -4),162                    'Velocity': Vector3(-0.0, -0.0, -0.0),163                    'Acceleration': Vector3(-0.0, -0.0, -0.0),164                    'Rotation': Quaternion(0, 0, 0, 1),165                    'AngularVelocity': Vector3(-0.0, -0.0, -0.0)166                },167                TextureEntry_=None,168            ),169        )170        self.message_handler.handle(msg)171        obj = self.region_object_manager.lookup_localid(local_id)172        self.assertEqual(obj.Position, Vector3(-2, -3, -4))173    def test_parent_tracking(self):174        """Are basic parenting scenarios handled?"""175        parent = self._create_object()176        child = self._create_object(parent_id=parent.LocalID)177        self.assertSequenceEqual([child.LocalID], parent.ChildIDs)178    def test_orphan_parent_tracking(self):179        child = self._create_object(local_id=2, parent_id=1)180        self.assertEqual({1}, self.region_object_manager.missing_locals)181        parent = self._create_object(local_id=1)182        self.assertEqual(set(), self.region_object_manager.missing_locals)183        self.assertSequenceEqual([child.LocalID], parent.ChildIDs)184    def test_killing_parent_kills_children(self):185        _child = self._create_object(local_id=2, parent_id=1)186        parent = self._create_object(local_id=1)187        # This should orphan the child again188        self._kill_object(parent.LocalID)189        parent = self._create_object(local_id=1)190        # We should not have picked up any children191        self.assertSequenceEqual([], parent.ChildIDs)192    def test_hierarchy_killed(self):193        _child = self._create_object(local_id=3, parent_id=2)194        _other_child = self._create_object(local_id=4, parent_id=2)195        _parent = self._create_object(local_id=2, parent_id=1)196        grandparent = self._create_object(local_id=1)197        # KillObject implicitly kills all known descendents at that point198        self._kill_object(grandparent.LocalID)199        self.assertEqual(0, len(self.region_object_manager))200    def test_hierarchy_avatar_not_killed(self):201        _child = self._create_object(local_id=3, parent_id=2)202        _parent = self._create_object(local_id=2, parent_id=1, pcode=PCode.AVATAR)203        grandparent = self._create_object(local_id=1)204        # KillObject should only "unsit" child avatars (does this require an ObjectUpdate205        # or is ParentID=0 implied?)206        self._kill_object(grandparent.LocalID)207        self.assertEqual(2, len(self.region_object_manager))208        self.assertIsNotNone(self.region_object_manager.lookup_localid(2))209    def test_attachment_orphan_parent_tracking(self):210        """211        Test that multi-level parenting trees handle orphaning correctly.212        Technically there can be at least 4 levels of parenting if sitting.213        object -> seated agent -> attachment root -> attachment child214        """215        child = self._create_object(local_id=3, parent_id=2)216        parent = self._create_object(local_id=2, parent_id=1)217        self.assertSequenceEqual([child.LocalID], parent.ChildIDs)218    def test_unparenting_succeeds(self):219        child = self._create_object(local_id=3, parent_id=2)220        parent = self._create_object(local_id=2)221        msg = self._create_object_update(local_id=child.LocalID, full_id=child.FullID, parent_id=0)222        self.message_handler.handle(msg)223        self.assertEqual(0, child.ParentID)224        self.assertSequenceEqual([], parent.ChildIDs)225    def test_reparenting_succeeds(self):226        child = self._create_object(local_id=3, parent_id=2)227        parent = self._create_object(local_id=2)228        second_parent = self._create_object(local_id=1)229        msg = self._create_object_update(local_id=child.LocalID,230                                         full_id=child.FullID, parent_id=second_parent.LocalID)231        self.message_handler.handle(msg)232        self.assertEqual(second_parent.LocalID, child.ParentID)233        self.assertSequenceEqual([], parent.ChildIDs)234        self.assertSequenceEqual([child.LocalID], second_parent.ChildIDs)235    def test_reparenting_without_known_parent_succeeds(self):236        child = self._create_object(local_id=3, parent_id=2)237        second_parent = self._create_object(local_id=1)238        msg = self._create_object_update(local_id=child.LocalID,239                                         full_id=child.FullID, parent_id=second_parent.LocalID)240        self.message_handler.handle(msg)241        # Create the original parent after its former child has been reparented242        parent = self._create_object(local_id=2)243        self.assertEqual(second_parent.LocalID, child.ParentID)244        self.assertSequenceEqual([], parent.ChildIDs)245        self.assertSequenceEqual([child.LocalID], second_parent.ChildIDs)246    def test_reparenting_with_neither_parent_known_succeeds(self):247        child = self._create_object(local_id=3, parent_id=2)248        msg = self._create_object_update(local_id=child.LocalID,249                                         full_id=child.FullID, parent_id=1)250        self.message_handler.handle(msg)251        second_parent = self._create_object(local_id=1)252        self.assertEqual(second_parent.LocalID, child.ParentID)253        self.assertSequenceEqual([child.LocalID], second_parent.ChildIDs)254    def test_property_changes_reported_correctly(self):255        obj = self._create_object(local_id=1)256        msg = self._create_object_update(local_id=obj.LocalID, full_id=obj.FullID, pos=(2.0, 2.0, 2.0))257        self.message_handler.handle(msg)258        events = self.object_addon.events259        self.assertEqual(2, len(events))260        self.assertEqual({"Position", "TextureEntry"}, events[1][2])261    def test_region_position(self):262        parent = self._create_object(pos=(0.0, 1.0, 0.0))263        child = self._create_object(parent_id=parent.LocalID, pos=(0.0, 1, 0.0))264        self.assertEqual(parent.RegionPosition, (0.0, 1.0, 0.0))265        self.assertEqual(child.RegionPosition, (0.0, 2.0, 0.0))266    def test_orphan_region_position(self):267        child = self._create_object(local_id=2, parent_id=1, pos=(0.0, 1, 0.0))268        with self.assertRaises(ValueError):269            getattr(child, "RegionPosition")270    def test_rotated_region_position(self):271        parent = self._create_object(pos=(0.0, 1.0, 0.0), rot=Quaternion.from_euler(0, 0, 180, True))272        child = self._create_object(parent_id=parent.LocalID, pos=(0.0, 1.0, 0.0))273        self.assertEqual(parent.RegionPosition, (0.0, 1.0, 0.0))274        self.assertEqual(child.RegionPosition, (0.0, 0.0, 0.0))275    def test_rotated_region_position_multi_level(self):276        rot = Quaternion.from_euler(0, 0, 180, True)277        grandparent = self._create_object(pos=(0.0, 1.0, 0.0), rot=rot)278        parent = self._create_object(parent_id=grandparent.LocalID, pos=(0.0, 1.0, 0.0), rot=rot)279        child = self._create_object(parent_id=parent.LocalID, pos=(1.0, 2.0, 0.0))280        self.assertEqual(grandparent.RegionPosition, (0.0, 1.0, 0.0))281        self.assertEqual(parent.RegionPosition, (0.0, 0.0, 0.0))282        self.assertEqual(child.RegionPosition, (1.0, 2.0, 0.0))283    def test_global_position(self):284        obj = self._create_object(pos=(0.0, 0.0, 0.0))285        self.assertEqual(obj.GlobalPosition, (0.0, 123.0, 0.0))286    def test_avatar_locations(self):287        agent1_id = UUID.random()288        agent2_id = UUID.random()289        self.message_handler.handle(Message(290            "CoarseLocationUpdate",291            Block("AgentData", AgentID=agent1_id),292            Block("AgentData", AgentID=agent2_id),293            Block("Location", X=1, Y=2, Z=3),294            Block("Location", X=2, Y=3, Z=4),295        ))296        self.assertDictEqual(self._get_avatar_positions(), {297            # CoarseLocation's Z axis is multiplied by 4298            agent1_id: Vector3(1, 2, 12),299            agent2_id: Vector3(2, 3, 16),300        })301        # Simulate an avatar sitting on an object302        seat_object = self._create_object(pos=(0, 0, 3))303        # If we have a real object pos it should override coarse pos304        avatar_obj = self._create_object(full_id=agent1_id, pcode=PCode.AVATAR,305                                         parent_id=seat_object.LocalID, pos=Vector3(0, 0, 2))306        self.assertDictEqual(self._get_avatar_positions(), {307            # Agent is seated, make sure this is region and not local pos308            agent1_id: Vector3(0, 0, 5),309            agent2_id: Vector3(2, 3, 16),310        })311        # Simulate missing parent for agent312        self._kill_object(seat_object.LocalID)313        self.assertDictEqual(self._get_avatar_positions(), {314            # Agent is seated, but we don't know its parent. We have315            # to use the coarse location.316            agent1_id: Vector3(1, 2, 12),317            agent2_id: Vector3(2, 3, 16),318        })319        # If the object is killed and no coarse pos, it shouldn't be in the dict320        # CoarseLocationUpdates are expected to be complete, so any agents missing321        # are no longer in the sim.322        self._kill_object(avatar_obj.LocalID)323        self.message_handler.handle(Message(324            "CoarseLocationUpdate",325            Block("AgentData", AgentID=agent2_id),326            Block("Location", X=2, Y=3, Z=4),327        ))328        self.assertDictEqual(self._get_avatar_positions(), {329            agent2_id: Vector3(2, 3, 16),330        })331        # 255 on Z axis means we can't guess the real Z332        self.message_handler.handle(Message(333            "CoarseLocationUpdate",334            Block("AgentData", AgentID=agent2_id),335            Block("Location", X=2, Y=3, Z=math.inf),336        ))337        self.assertDictEqual(self._get_avatar_positions(), {338            agent2_id: Vector3(2, 3, math.inf),339        })340        agent2_avatar = self.region_object_manager.lookup_avatar(agent2_id)341        self.assertEqual(agent2_avatar.GlobalPosition, Vector3(2, 126, math.inf))342    def test_name_cache(self):343        # Receiving an update with a NameValue for an avatar should update NameCache344        obj = self._create_object(345            pcode=PCode.AVATAR,346            namevalue='DisplayName STRING RW DS ð²ð«ð¦ð ð¬ð¡ð¢ð«ððªð¢\n'347                      'FirstName STRING RW DS firstname\n'348                      'LastName STRING RW DS Resident\n'349                      'Title STRING RW DS foo'.encode("utf8"),350        )351        self.assertEqual(self.session_manager.name_cache.lookup(obj.FullID).first_name, "firstname")352        av = self.region_object_manager.lookup_avatar(obj.FullID)353        self.assertEqual(av.Name, "ð²ð«ð¦ð ð¬ð¡ð¢ð«ððªð¢ (firstname Resident)")354        self.assertEqual(av.PreferredName, "ð²ð«ð¦ð ð¬ð¡ð¢ð«ððªð¢")355    def test_normalize_cache_data(self):356        normalized = normalize_object_update_compressed_data(OBJECT_UPDATE_COMPRESSED_DATA)357        expected = {358            'PSBlock': None,359            'ParentID': 0,360            'LocalID': 1234,361            'FullID': UUID('121210bf-1658-427e-8fb4-fb001acd9be5'),362            'PCode': PCode.PRIMITIVE,363            'State': 0,364            'CRC': 18381,365            'Material': 3,366            'ClickAction': 0,367            'Scale': Vector3(39.0, 39.0, 0.10000000149011612),368            'Position': Vector3(43.07024002075195, 79.34690856933594, 20.049999237060547),369            'Rotation': Quaternion(0.0, 0.0, -0.48543819785118103, 0.8742709854884798),370            'OwnerID': UUID('6b9bc4fe-330a-4f61-bbe2-e4b243ac37bd'),371            'AngularVelocity': Vector3(0.0, 0.0, 0.0791015625),372            'TreeSpecies': None,373            'ScratchPad': None,374            'Text': b'',375            'TextColor': b'',376            'MediaURL': b'',377            'Sound': UUID(),378            'SoundGain': 0.0,379            'SoundFlags': 0,380            'SoundRadius': 0.0,381            'NameValue': [],382            'PathCurve': 32,383            'ProfileCurve': 0,384            'PathBegin': 0,385            'PathEnd': 25600,386            'PathScaleX': 150,387            'PathScaleY': 0,388            'PathShearX': 0,389            'PathShearY': 0,390            'PathTwist': 0,391            'PathTwistBegin': 0,392            'PathRadiusOffset': 0,393            'PathTaperX': 0,394            'PathTaperY': 0,395            'PathRevolutions': 0,396            'PathSkew': 0,397            'ProfileBegin': 0,398            'ProfileEnd': 0,399            'ProfileHollow': 0,400        }401        filtered_normalized = {k: v for k, v in normalized.items() if k in expected}402        self.assertDictEqual(filtered_normalized, expected)403        sculpt_texture = normalized["ExtraParams"][ExtraParamType.SCULPT]["Texture"]404        self.assertEqual(sculpt_texture, UUID('89556747-24cb-43ed-920b-47caed15465f'))405        self.assertIsNotNone(normalized['TextureAnim'])406        self.assertIsNotNone(normalized['TextureEntry'])407    def test_object_cache(self):408        self.mock_get_region_object_cache_chain.return_value = RegionViewerObjectCacheChain([409            RegionViewerObjectCache(self.region.cache_id, [410                ViewerObjectCacheEntry(411                    local_id=1234,412                    crc=22,413                    data=OBJECT_UPDATE_COMPRESSED_DATA,414                )415            ])416        ])417        cache_msg = self._create_object_update_cached(1234, flags=4321)418        obj = self.region_object_manager.lookup_localid(1234)419        self.assertIsNone(obj)420        self.region_object_manager.load_cache()421        self.message_handler.handle(cache_msg)422        obj = self.region_object_manager.lookup_localid(1234)423        self.assertEqual(obj.FullID, UUID('121210bf-1658-427e-8fb4-fb001acd9be5'))424        # Flags from the ObjectUpdateCached should have been merged in425        self.assertEqual(obj.UpdateFlags, 4321)426    async def test_request_objects(self):427        # request five objects, three of which won't receive an ObjectUpdate428        futures = self.region_object_manager.request_objects((1234, 1235, 1236, 1237))429        self._create_object(1234)430        self._create_object(1235)431        done, pending = await asyncio.wait(futures, timeout=0.0001)432        objects = await asyncio.gather(*done)433        # wait() returns unordered results, so use a set.434        self.assertEqual(set(o.LocalID for o in objects), {1234, 1235})435        pending = list(pending)436        self.assertEqual(2, len(pending))437        pending_1, pending_2 = pending438        # Timing out should cancel439        with self.assertRaises(asyncio.TimeoutError):440            await asyncio.wait_for(pending_1, 0.00001)441        self.assertTrue(pending_1.cancelled())442        fut = self.region_object_manager.request_objects(1238)[0]443        self._kill_object(1238)444        self.assertTrue(fut.cancelled())445        # Object manager being cleared due to region death should cancel446        self.assertFalse(pending_2.cancelled())447        self.region_object_manager.clear()448        self.assertTrue(pending_2.cancelled())449        # The clear should have triggered the objects to be removed from the world view as well450        # as the region view451        self.assertEqual(0, len(self.session.objects))452        self.assertEqual(0, len(self.region_object_manager))453class SessionObjectManagerTests(ObjectManagerTestMixin, unittest.IsolatedAsyncioTestCase):454    async def asyncSetUp(self) -> None:455        await super().asyncSetUp()456        self.second_region = self.session.register_region(457            ("127.0.0.1", 9), "https://localhost:5", 124458        )459        self.session.objects.track_region_objects(124)460        self._setup_region_circuit(self.second_region)461    def test_get_fullid(self):462        obj = self._create_object()463        self.assertIs(self.session.objects.lookup_fullid(obj.FullID), obj)464        self._kill_object(obj.LocalID)465        self.assertIsNone(self.session.objects.lookup_fullid(obj.FullID))466    def test_region_handle_change(self):467        obj = self._create_object(region_handle=123)468        self.assertEqual(obj.RegionHandle, 123)469        self.assertIs(self.region.objects.lookup_fullid(obj.FullID), obj)470        self.assertIs(self.region.objects.lookup_localid(obj.LocalID), obj)471        # Send an update moving the object to the new region472        self._create_object(local_id=~obj.LocalID & 0xFFffFFff, full_id=obj.FullID, region_handle=124)473        self.assertEqual(obj.RegionHandle, 124)474        self.assertIsNone(self.region.objects.lookup_fullid(obj.FullID))475        self.assertIsNone(self.region.objects.lookup_localid(obj.LocalID))476        self.assertIs(self.second_region.objects.lookup_fullid(obj.FullID), obj)477        self.assertIs(self.second_region.objects.lookup_localid(obj.LocalID), obj)478        self.assertEqual(1, len(self.session.objects))479        self.assertEqual(0, len(self.region.objects))480        self.assertEqual(1, len(self.second_region.objects))481    def test_object_moved_to_bad_region(self):482        obj = self._create_object(region_handle=123)483        msg = self._create_object_update(484            local_id=~obj.LocalID & 0xFFffFFff, full_id=obj.FullID, region_handle=999)485        self.message_handler.handle(msg)486        # Should not be in this region anymore487        self.assertEqual(0, len(self.region_object_manager))488        # Should still be tracked by the session489        self.assertEqual(1, len(self.session.objects))490        self.assertIsNotNone(self.session.objects.lookup_fullid(obj.FullID))491    def test_linkset_region_handle_change(self):492        parent = self._create_object(region_handle=123)493        child = self._create_object(region_handle=123, parent_id=parent.LocalID)494        self._create_object(local_id=~parent.LocalID & 0xFFffFFff, full_id=parent.FullID, region_handle=124)495        # Children reference their parents, not the other way around. Moving this to a new region496        # should have cleared the list because it now has no children in the same region.497        self.assertEqual([], parent.ChildIDs)498        # Move the child to the same region499        self._create_object(500            local_id=child.LocalID, full_id=child.FullID, region_handle=124, parent_id=parent.LocalID)501        # Child should be back in the children list502        self.assertEqual([child.LocalID], parent.ChildIDs)503        self.assertEqual(parent.LocalID, child.ParentID)504        self.assertEqual(0, len(self.region.objects))505        self.assertEqual(2, len(self.second_region.objects))506        self.assertEqual(0, len(self.region.objects.missing_locals))507        self.assertEqual(0, len(self.second_region.objects.missing_locals))508    def test_all_objects(self):509        obj = self._create_object()510        self.assertEqual([obj], list(self.session.objects.all_objects))511    def test_all_avatars(self):512        obj = self._create_object(pcode=PCode.AVATAR)513        av_list = list(self.session.objects.all_avatars)514        self.assertEqual(1, len(av_list))515        self.assertEqual(obj, av_list[0].Object)516    def test_avatars_preference(self):517        # If we have a coarselocation for an avatar in one region and518        # an actual object in another, we should always prefer the519        # one with the actual object.520        av_1 = self._create_object(pcode=PCode.AVATAR, region_handle=123)521        av_2 = self._create_object(pcode=PCode.AVATAR, region_handle=124)522        # Coarse location shouldn't be used for either of these523        self.session.region_by_handle(123).message_handler.handle(Message(524            "CoarseLocationUpdate",525            Block("AgentData", AgentID=av_2.FullID),526            Block("Location", X=2, Y=3, Z=4),527        ))528        self.session.region_by_handle(124).message_handler.handle(Message(529            "CoarseLocationUpdate",530            Block("AgentData", AgentID=av_1.FullID),531            Block("Location", X=2, Y=3, Z=4),532        ))533        av_list = list(self.session.objects.all_avatars)534        self.assertEqual(2, len(av_list))535        self.assertTrue(all(a.Object for a in av_list))536    def test_lookup_avatar(self):537        av_1 = self._create_object(pcode=PCode.AVATAR)538        av_obj = self.session.objects.lookup_avatar(av_1.FullID)539        self.assertEqual(av_1.FullID, av_obj.FullID)540    async def test_requesting_properties(self):541        obj = self._create_object()542        futs = self.session.objects.request_object_properties(obj)543        self.message_handler.handle(Message(544            "ObjectProperties",545            Block("ObjectData", ObjectID=obj.FullID, Name="Foobar", TextureID=b""),546        ))547        await asyncio.wait_for(futs[0], timeout=0.0001)548        self.assertEqual(obj.Name, "Foobar")549    async def test_load_ancestors(self):550        child = self._create_object(region_handle=123, parent_id=1)551        parentless = self._create_object(region_handle=123)552        orphaned = self._create_object(region_handle=123, parent_id=9)553        async def _create_after():554            await asyncio.sleep(0.001)555            self._create_object(region_handle=123, local_id=child.ParentID)556        asyncio.create_task(_create_after())557        await self.session.objects.load_ancestors(child)558        await self.session.objects.load_ancestors(parentless)559        with self.assertRaises(asyncio.TimeoutError):560            await self.session.objects.load_ancestors(orphaned, wait_time=0.005)561    async def test_auto_request_objects(self):562        self.session_manager.settings.AUTOMATICALLY_REQUEST_MISSING_OBJECTS = True563        self.message_handler.handle(self._create_object_update_cached(1234))564        self.message_handler.handle(self._create_object_update_cached(1235))565        self.assertEqual({1234, 1235}, self.region_object_manager.queued_cache_misses)566        # Pretend viewer sent out its own RequestMultipleObjects567        self.message_handler.handle(Message(568            'RequestMultipleObjects',569            Block("RegionData", SessionID=self.session.id, AgentID=self.session.agent_id),570            Block(571                "ObjectData",572                ID=1234,573            )574        ))575        # Proxy should have killed its pending request for 1234576        self.assertEqual({1235}, self.region_object_manager.queued_cache_misses)577    async def test_auto_request_avatar_seats(self):578        # Avatars' parent links should always be requested regardless of579        # object auto-request setting's value.580        seat_id = 999581        av = self._create_object(pcode=PCode.AVATAR, parent_id=seat_id)582        self.assertEqual({seat_id}, self.region_object_manager.queued_cache_misses)583        # Need to wait for it to decide it's worth requesting584        await asyncio.sleep(0.22)585        self.assertEqual(set(), self.region_object_manager.queued_cache_misses)586        # Make sure we sent a request after the timeout587        req_msg = self.deserializer.deserialize(self.transport.packets[-1][0])588        self.assertEqual("RequestMultipleObjects", req_msg.name)589        self.assertEqual(590            [{'CacheMissType': 0, 'ID': seat_id}],591            req_msg.to_dict()['body']['ObjectData'],592        )593        # Parent should not be requested again if an unrelated property like pos changes594        self._create_object(local_id=av.LocalID, full_id=av.FullID,595                            pcode=PCode.AVATAR, parent_id=seat_id, pos=(1, 2, 9))596        self.assertEqual(set(), self.region_object_manager.queued_cache_misses)597    async def test_handle_object_update_event(self):598        with self.session.objects.events.subscribe_async(599            message_names=(ObjectUpdateType.OBJECT_UPDATE,),600            predicate=lambda e: e.object.UpdateFlags & JUST_CREATED_FLAGS and "LocalID" in e.updated,601        ) as get_events:602            self._create_object(local_id=999)603            evt = await asyncio.wait_for(get_events(), 1.0)604            self.assertEqual(999, evt.object.LocalID)605    async def test_handle_object_update_predicate(self):606        with self.session.objects.events.subscribe_async(607            message_names=(ObjectUpdateType.OBJECT_UPDATE,),608        ) as get_events:609            self._create_object(local_id=999)610            evt = await asyncio.wait_for(get_events(), 1.0)611            self.assertEqual(999, evt.object.LocalID)612    async def test_handle_object_update_events_two_subscribers(self):613        with self.session.objects.events.subscribe_async(614            message_names=(ObjectUpdateType.OBJECT_UPDATE,),615        ) as get_events:616            with self.session.objects.events.subscribe_async(617                    message_names=(ObjectUpdateType.OBJECT_UPDATE,),618            ) as get_events2:619                self._create_object(local_id=999)620                evt = await asyncio.wait_for(get_events(), 1.0)621                evt2 = await asyncio.wait_for(get_events2(), 1.0)622                self.assertEqual(999, evt.object.LocalID)623                self.assertEqual(evt, evt2)624    async def test_handle_object_update_events_two_subscribers_timeout(self):625        with self.session.objects.events.subscribe_async(626            message_names=(ObjectUpdateType.OBJECT_UPDATE,),627        ) as get_events:628            with self.session.objects.events.subscribe_async(629                    message_names=(ObjectUpdateType.OBJECT_UPDATE,),630            ) as get_events2:631                self._create_object(local_id=999)632                evt = asyncio.wait_for(get_events(), 0.01)633                evt2 = asyncio.wait_for(get_events2(), 0.01)...base.py
Source:base.py  
...34        return self.client.login(username=user.username,35                                 password=password)36    def create_project(self, title, description='', **kwargs):37        kwargs['theme'] = kwargs.get('theme', self.default_theme)38        return self._create_object(39            Project, ('title', title), ('description', description),40            **kwargs41        )42    def create_user(self, username, **kwargs):43        kwargs.update({'username': username})44        kwargs['password'] = kwargs.get('password', username)45        user = User.objects.create_user(**kwargs)46        user.save()47        return user48    def _create_object(self, cls, *args, **kwargs):49        for name, val in args:50            kwargs[name] = val51        obj = cls.objects.create(**kwargs)52        obj.save()53        return obj54    def create_access(self, user, project, can_edit=False):55        return self._create_object(56            ProjectAccess,57            ('user', user), ('project', project), ('can_edit', can_edit),58        )59    def create_page(self, title, **kwargs):60        return self._create_object(Page, ('title', title), **kwargs)61    def create_post(self, title, content, **kwargs):62        timestamp = timezone.now()63        kwargs['date_created'] = kwargs.get('date_created', timestamp)64        kwargs['date_updated'] = kwargs.get('date_updated', timestamp)65        return self._create_object(66            Post,67            ('title', title), ('content', content),68            **kwargs69        )70    def create_category(self, title, **kwargs):71        return self._create_object(Category, ('title', title), **kwargs)72    def create_tag(self, title, **kwargs):73        return self._create_object(Tag, ('title', title), **kwargs)74    def create_theme(self, title, markup, **kwargs):75        kwargs['creator'] = kwargs.get('creator', self.admin_user)76        kwargs['filepath'] = kwargs.get('filepath', '')77        return self._create_object(78            Theme,79            ('title', title), ('body_markup', markup),80            **kwargs81        )82    def create_project_plugin(self, title, **kwargs):83        kwargs['markup'] = kwargs.get('markup', 'markup')84        return self._create_object(ProjectPlugin, ('title', title), **kwargs)85    def create_page_plugin(self, title, **kwargs):86        kwargs['head_markup'] = kwargs.get('head_markup', 'head_markup')87        kwargs['body_markup'] = kwargs.get('body_markup', 'body_markup')88        return self._create_object(PagePlugin, ('title', title), **kwargs)89class FuglViewTestCase(FuglTestCase):90    def setUp(self):91        super().setUpTheme()92        self.client = Client()93    def tearDown(self):...factories.py
Source:factories.py  
1from test_app.models import *2def _create_object(model, **kw):3    obj = model(**kw)4    obj.save()5    return obj6def create_entity(**kw):7    if 'fk_entity' not in kw:8        kw['fk_entity'] = _create_object(FKEntity, value='FK Value')9    if 'o2o_entity' not in kw:10        kw['o2o_entity'] = _create_object(OneFromEntity, value='Value')11    return _create_object(Entity, **kw)12def create_related_entity(**kw):13    return _create_object(RelatedEntity, **kw)14def create_deep_related_entity(**kw):15    return _create_object(DeepRelatedEntity, **kw)16def create_sort_entity(**kw):17    return _create_object(SortEntity, **kw)18def create_sort_related_entity_a(**kw):19    return _create_object(SortRelatedEntityA, **kw)20def create_sort_related_entity_b(**kw):21    return _create_object(SortRelatedEntityB, **kw)22def create_sort_related_entity_c(**kw):23    return _create_object(SortRelatedEntityC, **kw)24def create_O2O_to_entity(**kw):...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
