blob: 87e7627dcbd6db678cb5dc541e4b69b0fa7b7671 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
from sarif import *
import pytest
@pytest.fixture(scope='function', autouse=True)
def sarif():
return sarif_from_env()
def test_basics(sarif):
schema = sarif['$schema']
assert schema == "https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json"
version = sarif['version']
assert version == "2.1.0"
def test_execution_unsuccessful(sarif):
runs = sarif['runs']
run = runs[0]
invocations = run['invocations']
assert len(invocations) == 1
invocation = invocations[0]
# We expect the errors to make executionSuccessful be false
assert invocation['executionSuccessful'] == False
def test_location_relationships(sarif):
runs = sarif['runs']
run = runs[0]
results = run['results']
# We expect a pair of errors, each with a note, and include chains.
# The textual form of these four diagnostics would look like this:
# . In file included from PATH/include-chain-1.h:5,
# . from PATH/include-chain.c:9:
# . PATH/include-chain-1-2.h:1:6: error: conflicting types for 'p'; have 'char'
# . 1 | char p;
# . | ^
# . In file included from PATH/include-chain-1.h:2:
# . PATH/include-chain-1-1.h:1:5: note: previous declaration of 'p' with type 'int'
# . 1 | int p;
# . | ^
# . PATH/include-chain-1-2.h:2:6: error: conflicting types for 'q'; have 'char'
# . 2 | char q;
# . | ^
# . PATH/include-chain-1-1.h:2:5: note: previous declaration of 'q' with type 'int'
# . 2 | int q;
# . | ^
assert len(results) == 2
result = results[0]
assert result['level'] == 'error'
assert result['message']['text'] == "conflicting types for 'p'; have 'char'"
locations = result['locations']
assert len(locations) == 1
location = locations[0]
assert 'id' in location
assert get_location_artifact_uri(location).endswith('include-chain-1-2.h')
assert get_location_snippet_text(location) == "char p;\n"
# We expect 4 related locations: one for the "note"
# and three for describing include chains
relatedLocations = result['relatedLocations']
assert len(relatedLocations) == 4
# We expect a related location representing the note:
# . In file included from PATH/include-chain-1.h:2:
# . from PATH/include-chain.c:9:
# . PATH/include-chain-1-1.h:1:5: note: previous declaration of 'p' with type 'int'
# . 1 | int p;
# . | ^
note = relatedLocations[0]
assert 'id' in note
assert note['message']['text'] == "previous declaration of 'p' with type 'int'"
assert get_location_artifact_uri(note).endswith('include-chain-1-1.h')
assert get_location_snippet_text(note) == "int p;\n"
# We expect three more related locations for the two include chains
# The "#include "include-chain-1-2.h" line in include-chain-1.h:
hash_include_1_2_h = relatedLocations[1]
assert 'id' in hash_include_1_2_h
assert get_location_snippet_text(hash_include_1_2_h) == '#include "include-chain-1-2.h"\n'
assert get_location_artifact_uri(hash_include_1_2_h).endswith('include-chain-1.h')
# The "#include "include-chain-1-1.h" line in include-chain-1.h:
hash_include_1_1_h = relatedLocations[2]
assert 'id' in hash_include_1_1_h
assert get_location_snippet_text(hash_include_1_1_h) == '#include "include-chain-1-1.h"\n'
assert get_location_artifact_uri(hash_include_1_1_h).endswith('include-chain-1.h')
# The "#include "include-chain-1.h" line in include-chain-1.c:
hash_include_1_h = relatedLocations[3]
assert 'id' in hash_include_1_h
assert get_location_snippet_text(hash_include_1_h) == '#include "include-chain-1.h"\n'
assert get_location_artifact_uri(hash_include_1_h).endswith('include-chain-1.c')
# Check the various relationships; we expect a directed graph of edges
# representing the various "isIncludedBy" and "includes" relationships.
# The primary location should be "isIncludedBy" the "#include "include-chain-1-2.h" line
assert len(location['relationships']) == 1
assert location['relationships'][0]['target'] == hash_include_1_2_h['id']
assert location['relationships'][0]['kinds'] == ["isIncludedBy"]
# The note should be "isIncludedBy" the "#include "include-chain-1-1.h" line
assert len(note['relationships']) == 1
assert note['relationships'][0]['target'] == hash_include_1_1_h['id']
assert note['relationships'][0]['kinds'] == ["isIncludedBy"]
# The "#include "include-chain-1-2.h" line:
assert len(hash_include_1_2_h['relationships']) == 2
assert hash_include_1_2_h['relationships'][0]['target'] == location['id']
assert hash_include_1_2_h['relationships'][0]['kinds'] == ["includes"]
assert hash_include_1_2_h['relationships'][1]['target'] == hash_include_1_h['id']
assert hash_include_1_2_h['relationships'][1]['kinds'] == ["isIncludedBy"]
# The "#include "include-chain-1-1.h" line:
assert len(hash_include_1_1_h['relationships']) == 2
assert hash_include_1_1_h['relationships'][0]['target'] == note['id']
assert hash_include_1_1_h['relationships'][0]['kinds'] == ["includes"]
assert hash_include_1_1_h['relationships'][1]['target'] == hash_include_1_h['id']
assert hash_include_1_1_h['relationships'][1]['kinds'] == ["isIncludedBy"]
# The "#include "include-chain-1.h" line in include-chain-1.c:
assert len(hash_include_1_h['relationships']) == 2
assert hash_include_1_h['relationships'][0]['target'] == hash_include_1_2_h['id']
assert hash_include_1_h['relationships'][0]['kinds'] == ["includes"]
assert hash_include_1_h['relationships'][1]['target'] == hash_include_1_1_h['id']
assert hash_include_1_h['relationships'][1]['kinds'] == ["includes"]
# We expect similar for the 2nd error
assert results[1]['level'] == 'error'
assert results[1]['message']['text'] == "conflicting types for 'q'; have 'char'"
assert len(results[1]['relatedLocations']) == 4
|