def testTraceCursorLocation(self):
        run = Run(id=1, date=datetime.now(), status=RunStatus.FINISHED)
        issue = self._generic_issue()
        issue_instance = self._generic_issue_instance()
        trace_frames = [
            TraceFrame(
                id=1,
                kind=TraceKind.POSTCONDITION,
                caller="call1",
                caller_port="root",
                callee="leaf",
                callee_port="source",
                callee_location=SourceLocation(1, 1),
                filename="file.py",
                run_id=1,
            ),
            TraceFrame(
                id=2,
                kind=TraceKind.PRECONDITION,
                caller="call1",
                caller_port="root",
                callee="leaf",
                callee_port="sink",
                callee_location=SourceLocation(1, 2),
                filename="file.py",
                run_id=1,
            ),
        ]
        assocs = [
            IssueInstanceTraceFrameAssoc(trace_frame_id=1, issue_instance_id=1),
            IssueInstanceTraceFrameAssoc(trace_frame_id=2, issue_instance_id=1),
            TraceFrameLeafAssoc(trace_frame_id=1, leaf_id=1),
            TraceFrameLeafAssoc(trace_frame_id=2, leaf_id=1),
        ]
        with self.db.make_session() as session:
            session.add(run)
            session.add(issue)
            session.add(issue_instance)
            self._add_to_session(session, trace_frames)
            self._add_to_session(session, assocs)
            session.commit()

        self.interactive.setup()
        self.interactive.set_issue(1)
        self.assertEqual(self.interactive.current_trace_frame_index, 1)
        self.interactive.next_cursor_location()
        self.assertEqual(self.interactive.current_trace_frame_index, 2)
        self.interactive.next_cursor_location()
        self.assertEqual(self.interactive.current_trace_frame_index, 2)
        self.interactive.prev_cursor_location()
        self.assertEqual(self.interactive.current_trace_frame_index, 1)
        self.interactive.prev_cursor_location()
        self.assertEqual(self.interactive.current_trace_frame_index, 0)
        self.interactive.prev_cursor_location()
        self.assertEqual(self.interactive.current_trace_frame_index, 0)
    def testTrace(self):
        run = Run(id=1, date=datetime.now(), status=RunStatus.FINISHED)
        issue = self._generic_issue()
        issue_instance = self._generic_issue_instance()
        trace_frames = [
            TraceFrame(
                id=1,
                kind=TraceKind.POSTCONDITION,
                caller="call1",
                caller_port="root",
                callee="leaf",
                callee_port="source",
                callee_location=SourceLocation(1, 1, 1),
                filename="file.py",
                run_id=1,
            ),
            TraceFrame(
                id=2,
                kind=TraceKind.PRECONDITION,
                caller="call1",
                caller_port="root",
                callee="leaf",
                callee_port="sink",
                callee_location=SourceLocation(1, 1, 2),
                filename="file.py",
                run_id=1,
            ),
        ]
        assocs = [
            IssueInstanceTraceFrameAssoc(trace_frame_id=1, issue_instance_id=1),
            IssueInstanceTraceFrameAssoc(trace_frame_id=2, issue_instance_id=1),
            TraceFrameLeafAssoc(trace_frame_id=1, leaf_id=1),
            TraceFrameLeafAssoc(trace_frame_id=2, leaf_id=1),
        ]

        with self.db.make_session() as session:
            session.add(run)
            session.add(issue)
            session.add(issue_instance)
            self._add_to_session(session, trace_frames)
            self._add_to_session(session, assocs)
            session.commit()

        self.interactive.setup()
        self.interactive.trace()
        stderr = self.stderr.getvalue().strip()
        self.assertIn("Use 'set_issue(ID)' to select an issue first.", stderr)

        self.interactive.set_issue(1)
        self.interactive.trace()
        output = self.stdout.getvalue().strip()
        self.assertIn("                leaf       source file.py:1|1|1", output)
        self.assertIn(" -->            call1      root   file.py:1|2|3", output)
        self.assertIn("                leaf       sink   file.py:1|1|2", output)
    def testTraceMissingFrames(self):
        run = Run(id=1, date=datetime.now(), status=RunStatus.FINISHED)
        issue = self._generic_issue()
        issue_instance = self._generic_issue_instance()
        trace_frames = [
            TraceFrame(
                id=1,
                kind=TraceKind.POSTCONDITION,
                caller="call1",
                caller_port="root",
                callee="leaf",
                callee_port="source",
                callee_location=SourceLocation(1, 1, 1),
                filename="file.py",
                run_id=1,
            ),
            TraceFrame(
                id=2,
                kind=TraceKind.PRECONDITION,
                caller="call1",
                caller_port="root",
                callee="call2",
                callee_port="param0",
                callee_location=SourceLocation(1, 1, 1),
                filename="file.py",
                run_id=1,
            ),
        ]
        assocs = [
            IssueInstanceTraceFrameAssoc(trace_frame_id=1, issue_instance_id=1),
            IssueInstanceTraceFrameAssoc(trace_frame_id=2, issue_instance_id=1),
            TraceFrameLeafAssoc(trace_frame_id=1, leaf_id=1),
            TraceFrameLeafAssoc(trace_frame_id=2, leaf_id=1),
        ]

        with self.db.make_session() as session:
            session.add(run)
            session.add(issue)
            session.add(issue_instance)
            self._add_to_session(session, trace_frames)
            self._add_to_session(session, assocs)
            session.commit()

        self.interactive.setup()
        self.interactive.set_issue(1)
        self.interactive.trace()
        stdout = self.stdout.getvalue().strip()
        self.assertIn("Missing trace frame: call2:param0", stdout)
    def testTraceNoSinks(self):
        run = Run(id=1, date=datetime.now(), status=RunStatus.FINISHED)
        issue = self._generic_issue()
        issue_instance = self._generic_issue_instance()
        trace_frame = TraceFrame(
            id=1,
            kind=TraceKind.POSTCONDITION,
            caller="call1",
            caller_port="root",
            callee="leaf",
            callee_port="source",
            callee_location=SourceLocation(1, 1),
            filename="file.py",
            run_id=1,
        )
        source = SharedText(id=1, contents="source1", kind=SharedTextKind.SOURCE)
        assocs = [
            IssueInstanceTraceFrameAssoc(trace_frame_id=1, issue_instance_id=1),
            TraceFrameLeafAssoc(trace_frame_id=1, leaf_id=1),
        ]
        with self.db.make_session() as session:
            session.add(run)
            session.add(issue)
            session.add(issue_instance)
            session.add(trace_frame)
            session.add(source)
            self._add_to_session(session, assocs)
            session.commit()

        self.interactive.setup()
        self.interactive.sources = {"source1"}
        self.interactive.set_issue(1)
        self._clear_stdout()
        self.interactive.trace()
        self.assertEqual(
            self.stdout.getvalue().split("\n"),
            [
                "     [branches] [callable] [port] [location]",
                "                leaf       source file.py:1|1|1",
                " -->            call1      root   file.py:1|2|3",
                "",
            ],
        )
    def _set_up_branched_trace(self):
        run = Run(id=1, date=datetime.now(), status=RunStatus.FINISHED)
        issue = self._generic_issue()
        issue_instance = self._generic_issue_instance()
        messages = [
            SharedText(id=1, contents="source1", kind=SharedTextKind.SOURCE),
            SharedText(id=2, contents="sink1", kind=SharedTextKind.SINK),
        ]
        trace_frames = []
        assocs = [
            IssueInstanceSharedTextAssoc(issue_instance_id=1, shared_text_id=1),
            IssueInstanceSharedTextAssoc(issue_instance_id=1, shared_text_id=2),
        ]
        for i in range(6):
            trace_frames.append(
                TraceFrame(
                    id=i + 1,
                    caller="call1",
                    caller_port="root",
                    filename="file.py",
                    callee_location=SourceLocation(i, i, i),
                    run_id=1,
                )
            )
            if i < 2:  # 2 postconditions
                trace_frames[i].kind = TraceKind.POSTCONDITION
                trace_frames[i].callee = "leaf"
                trace_frames[i].callee_port = "source"
                assocs.append(
                    TraceFrameLeafAssoc(trace_frame_id=i + 1, leaf_id=1, trace_length=0)
                )
                assocs.append(
                    IssueInstanceTraceFrameAssoc(
                        trace_frame_id=i + 1, issue_instance_id=1
                    )
                )
            elif i < 4:
                trace_frames[i].kind = TraceKind.PRECONDITION
                trace_frames[i].callee = "call2"
                trace_frames[i].callee_port = "param2"
                assocs.append(
                    TraceFrameLeafAssoc(trace_frame_id=i + 1, leaf_id=2, trace_length=1)
                )
                assocs.append(
                    IssueInstanceTraceFrameAssoc(
                        trace_frame_id=i + 1, issue_instance_id=1
                    )
                )
            else:
                trace_frames[i].kind = TraceKind.PRECONDITION
                trace_frames[i].caller = "call2"
                trace_frames[i].caller_port = "param2"
                trace_frames[i].callee = "leaf"
                trace_frames[i].callee_port = "sink"
                assocs.append(
                    TraceFrameLeafAssoc(trace_frame_id=i + 1, leaf_id=2, trace_length=0)
                )

        with self.db.make_session() as session:
            session.add(run)
            session.add(issue)
            session.add(issue_instance)
            self._add_to_session(session, messages)
            self._add_to_session(session, trace_frames)
            self._add_to_session(session, assocs)
            session.commit()
    def testBranchPrefixLengthChanges(self):
        run = Run(id=1, date=datetime.now(), status=RunStatus.FINISHED)
        issue = self._generic_issue()
        issue_instance = self._generic_issue_instance()
        messages = [
            SharedText(id=1, contents="source1", kind=SharedTextKind.SOURCE),
            SharedText(id=2, contents="sink1", kind=SharedTextKind.SINK),
        ]
        trace_frames = [
            TraceFrame(
                id=1,
                kind=TraceKind.POSTCONDITION,
                caller="call1",
                caller_port="root",
                callee="leaf",
                callee_port="source",
                callee_location=SourceLocation(1, 1),
                filename="file.py",
                run_id=1,
            ),
            TraceFrame(
                id=2,
                kind=TraceKind.POSTCONDITION,
                caller="call1",
                caller_port="root",
                callee="prev_call",
                callee_port="result",
                callee_location=SourceLocation(1, 1),
                filename="file.py",
                run_id=1,
            ),
            TraceFrame(
                id=3,
                kind=TraceKind.POSTCONDITION,
                caller="prev_call",
                caller_port="result",
                callee="leaf",
                callee_port="source",
                callee_location=SourceLocation(1, 1),
                filename="file.py",
                run_id=1,
            ),
            TraceFrame(
                id=4,
                kind=TraceKind.PRECONDITION,
                caller="call1",
                caller_port="root",
                callee="leaf",
                callee_port="sink",
                callee_location=SourceLocation(1, 2),
                filename="file.py",
                run_id=1,
            ),
        ]
        assocs = [
            IssueInstanceSharedTextAssoc(issue_instance_id=1, shared_text_id=1),
            IssueInstanceSharedTextAssoc(issue_instance_id=1, shared_text_id=2),
            IssueInstanceTraceFrameAssoc(issue_instance_id=1, trace_frame_id=1),
            IssueInstanceTraceFrameAssoc(issue_instance_id=1, trace_frame_id=2),
            IssueInstanceTraceFrameAssoc(issue_instance_id=1, trace_frame_id=4),
            TraceFrameLeafAssoc(trace_frame_id=1, leaf_id=1, trace_length=0),
            TraceFrameLeafAssoc(trace_frame_id=2, leaf_id=1, trace_length=1),
            TraceFrameLeafAssoc(trace_frame_id=3, leaf_id=1, trace_length=0),
            TraceFrameLeafAssoc(trace_frame_id=4, leaf_id=2, trace_length=0),
        ]
        with self.db.make_session() as session:
            session.add(run)
            session.add(issue)
            session.add(issue_instance)
            self._add_to_session(session, messages)
            self._add_to_session(session, trace_frames)
            self._add_to_session(session, assocs)
            session.commit()

        self.interactive.setup()
        self.interactive.set_issue(1)

        self._clear_stdout()
        self.interactive.prev_cursor_location()
        self.assertEqual(
            self.stdout.getvalue().split("\n"),
            [
                "     [branches] [callable] [port] [location]",
                " --> + 2        leaf       source file.py:1|1|1",
                "                call1      root   file.py:1|2|3",
                "                leaf       sink   file.py:1|2|2",
                "",
            ],
        )

        self._clear_stdout()
        self.interactive.branch(1)
        self.assertEqual(
            self.stdout.getvalue().split("\n"),
            [
                "     [branches] [callable] [port] [location]",
                "                leaf       source file.py:1|1|1",
                " --> + 2        prev_call  result file.py:1|1|1",
                "                call1      root   file.py:1|2|3",
                "                leaf       sink   file.py:1|2|2",
                "",
            ],
        )

        self._clear_stdout()
        self.interactive.expand()
        output = self.stdout.getvalue().strip()
        self.assertIn("[*] prev_call : result", output)
        self.assertIn("        [1 hops: source1]", output)
Exemple #7
0
 def add_issue_instance_trace_frame_assoc(self, issue_instance, trace_frame):
     self.add(
         IssueInstanceTraceFrameAssoc.Record(
             issue_instance_id=issue_instance.id, trace_frame_id=trace_frame.id
         )
     )