def test_with_profile(self): # It's hard to get coverage for trace function inside progshot # because normally it's triggered by settrace, which is used # by coverage.py for coverage stat. However, we can use setprofile # to simulate the process and get some coverage def stub(): pass p = progshot.ProgShot(save_at_exit=False) # For sys.settrace, if "call" returns None, then "return" will never # trigger, so we can keep count of depth. For sys.profile, "call" # and "return" will always trigger, so we set curr_depth to a larger # value tf = TraceFunc(capture=p.capture, depth=8, outer=0, curr_depth=6) sys.setprofile(tf) # Trigger the trace function p.config(save_at_exit=False) # sanity check for setprofile stub() sys.setprofile(None) # call to stub will not be captured, only return self.assertEqual(len(p._films), 1) p = progshot.ProgShot(save_at_exit=False) frames = inspect.getouterframes(inspect.currentframe()) tf = TraceFunc(capture=p.capture, depth=10, outer=0, curr_depth=8) sys.setprofile(tf) _ = Film(frames[-1:]) sys.setprofile(None) self.assertGreater(len(p._films), 30)
def test_capture(self): ps = progshot.ProgShot(save_at_exit=False) ps.capture() ps.dump("test.pshot") self.assertTrue(os.path.exists("test.pshot")) self.assertTrue(os.stat("test.pshot").st_size > 0) os.remove("test.pshot")
def test_capture_without_filename(self): def f(ps): ps.capture() ps = progshot.ProgShot(save_at_exit=False) with patch.object(inspect, "getsourcelines", return_value=None, side_effect=OSError()) as _: f(ps) film = Film(ps._films[-1]) self.assertEqual(film.frames[0].start_lineno, -1) self.assertEqual(film.frames[0].frame_lines, 0)
def test_is_ins_local(self): p = progshot.ProgShot(save_at_exit=False) tf = TraceFunc(capture=p.capture, depth=1, outer=0) self.assertTrue( all([ tf._is_ins_local(ins) for ins in dis.get_instructions("a = 2") ])) self.assertFalse( all([ tf._is_ins_local(ins) for ins in dis.get_instructions("a[3] = 2") ]))
def test_dump(self): ps = progshot.ProgShot(save_at_exit=False) ps.capture() with tempfile.NamedTemporaryFile(mode="w", suffix=".pshot", delete=False) as f: ps.dump(f.name, clear_data=False) self.assertTrue(os.path.exists(f.name)) os.remove(f.name) with tempfile.NamedTemporaryFile(mode="w", suffix=".pshot", delete=False) as f: ps.config(filename=f.name) ps.dump() self.assertTrue(os.path.exists(f.name)) os.remove(f.name)
def test_config(self): ps = progshot.ProgShot() self.assertEqual(ps._save_at_exit, True) ps.config(save_at_exit=False) self.assertEqual(ps._save_at_exit, False) ps.config(save_at_exit=True) self.assertEqual(ps._save_at_exit, True) with self.assertRaises(TypeError): ps.config(save_at_exit="False") with self.assertRaises(ValueError): ps.config(filename=123) ps.config(depth=3) self.assertEqual(ps._trace_config["depth"], 3) with self.assertRaises(ValueError): ps.config(depth="lol")
def test_basic(self): p = progshot.ProgShot(save_at_exit=False) tf = TraceFunc(capture=p.capture, depth=1, outer=0) frame = inspect.currentframe() # Enter the actual call tf(frame, "call", None) tf(frame, "line", None) # Enter the call that's not supposed to trace # We should return None to turn off the trace local_tf = tf(frame, "call", None) self.assertIs(local_tf, None) # We returned from the call already, it's not # recorded because no local trace function is set tf(frame, "line", None) tf(frame, "return", None) self.assertEqual(len(p._films), 3)
def test_with(self): ps = progshot.ProgShot(save_at_exit=False) with ps.shoot(): _ = 1 _ = 2 self.assertEqual(len(ps._films), 2)
def test_capture_lambda(self): ps = progshot.ProgShot(save_at_exit=False) _ = max([1, 2, 3], key=lambda _: ps.capture() or 1) self.assertEqual(len(ps._films), 3)