import unittest from lihont import bar_patch ON_RESUME = """\ .class public Lcom/ss/android/ugc/aweme/main/MainActivity; .super LX/0tPX; .method public onResume()V .registers 5 const v0, 0x117de invoke-static {v0}, Lcom/bytedance/pumbaa/utility/method_id/MethodIDManager;->push(I)Z move-result v3 const/4 v0, 0x1 const-string v2, "com.ss.android.ugc.aweme.main.MainActivity" const-string v1, "onResume" invoke-static {v2, v1, v0}, Lcom/bytedance/apm/agent/v2/instrumentation/ActivityAgent;->onTrace(Ljava/lang/String;Ljava/lang/String;Z)V invoke-super {p0}, LX/1EKk;->onResume()V const/4 v0, 0x0 invoke-static {v2, v1, v0}, Lcom/bytedance/apm/agent/v2/instrumentation/ActivityAgent;->onTrace(Ljava/lang/String;Ljava/lang/String;Z)V return-void .end method .method public onStart()V .registers 4 invoke-super {p0}, LX/1EKk;->onStart()V return-void .end method """ class BarPatchTest(unittest.TestCase): def test_hook_follows_the_super_call_and_nothing_else_changes(self): patched = bar_patch.rewrite_main_activity(ON_RESUME) call = " invoke-static {p0}, " + bar_patch.HOOK self.assertEqual(1, patched.count(call)) self.assertLess(patched.index("->onResume()V"), patched.index(call)) self.assertLess(patched.index(call), patched.index("const/4 v0, 0x0")) # onStart's own super call is left alone and the rest of the file is byte for byte the same self.assertEqual(ON_RESUME, patched.replace("\n" + call + "\n", "", 1)) def test_it_refuses_to_patch_twice(self): patched = bar_patch.rewrite_main_activity(ON_RESUME) with self.assertRaises(ValueError): bar_patch.rewrite_main_activity(patched) def test_it_refuses_a_method_it_does_not_recognise(self): with self.assertRaises(ValueError): bar_patch.rewrite_main_activity(ON_RESUME.replace("->onResume()V", "->onPause()V")) with self.assertRaises(ValueError): bar_patch.rewrite_main_activity(".class public Lx;\n.super Ljava/lang/Object;\n") def test_runtime_target_is_the_hook(self): self.assertEqual([bar_patch.HOOK], bar_patch.runtime_targets()) if __name__ == "__main__": unittest.main()