@@ -29,14 +29,26 @@ class L2SchemaOracleTest {
2929
3030 private static final ObjectMapper MAPPER = new ObjectMapper ();
3131
32+ private static final String APP_ID = CanId .applicationId ("myapp" );
33+ private static final String USER_TYPE =
34+ CanId .childId (CanId .moduleId (APP_ID , "src/main/java/org/example/User.java" ), "User" );
35+ private static final String USER_HELLO = USER_TYPE + "/helloString()" ;
36+ private static final String USER_LOG = USER_TYPE + "/log()" ;
37+ private static final String A_TYPE = CanId .childId (CanId .moduleId (APP_ID , "A.java" ), "A" );
38+ private static final String A_F = A_TYPE + "/f()" ;
39+ private static final String A_G = A_TYPE + "/g()" ;
40+ private static final String STRING_VALUE_OF = CanId .externalId ("myapp" , "java.lang.String" , "valueOf(int)" );
41+ private static final String STRING_CASE_ORDER =
42+ CanId .externalId ("myapp" , "java.lang.String" , "CASE_INSENSITIVE_ORDER" );
43+
3244 /** Wrap application-level members in an otherwise-minimal conformant envelope. */
3345 private static String payload (String applicationMembers ) {
3446 return "{"
3547 + "\" schema_version\" :\" 2.0.0\" ,"
3648 + "\" language\" :\" java\" ,"
3749 + "\" max_level\" :2,"
3850 + "\" application\" :{"
39- + "\" id\" :\" can://java/myapp \" ,"
51+ + "\" id\" :\" " + APP_ID + " \" ,"
4052 + "\" kind\" :\" application\" ,"
4153 + "\" symbol_table\" :{}"
4254 + (applicationMembers .isEmpty () ? "" : "," + applicationMembers )
@@ -62,12 +74,12 @@ private static void assertRejected(String json, String because) throws IOExcepti
6274 }
6375
6476 private static final String EDGE = "{"
65- + "\" src\" :\" can://java/myapp/src/main/java/org/example/User.java/User/helloString() \" ,"
66- + "\" dst\" :\" can://java/myapp/src/main/java/org/example/User.java/User/log() \" ,"
77+ + "\" src\" :\" " + USER_HELLO + " \" ,"
78+ + "\" dst\" :\" " + USER_LOG + " \" ,"
6779 + "\" prov\" :[\" declared\" ,\" rta\" ],"
6880 + "\" weight\" :2}" ;
6981
70- private static final String EXTERNAL = "\" can://java/myapp/@external/java.lang.String/valueOf(int) \" :{"
82+ private static final String EXTERNAL = "\" " + STRING_VALUE_OF + " \" :{"
7183 + "\" kind\" :\" method\" ,"
7284 + "\" signature\" :\" valueOf(int)\" ,"
7385 + "\" declaring_type\" :\" java.lang.String\" }" ;
@@ -86,26 +98,26 @@ void anL1PayloadCarryingNeitherSurfaceStillValidates() throws IOException {
8698 @ Test
8799 void anEdgeMissingItsWeightIsRejected () throws IOException {
88100 assertRejected (payload ("\" call_graph\" :[{"
89- + "\" src\" :\" can://java/myapp/A.java/A/f() \" ,"
90- + "\" dst\" :\" can://java/myapp/A.java/A/g() \" ,"
101+ + "\" src\" :\" " + A_F + " \" ,"
102+ + "\" dst\" :\" " + A_G + " \" ,"
91103 + "\" prov\" :[\" declared\" ]}]" ),
92104 "weight is the call-site count, so an edge without one asserts nothing about strength" );
93105 }
94106
95107 @ Test
96108 void aZeroWeightEdgeIsRejected () throws IOException {
97109 assertRejected (payload ("\" call_graph\" :[{"
98- + "\" src\" :\" can://java/myapp/A.java/A/f() \" ,"
99- + "\" dst\" :\" can://java/myapp/A.java/A/g() \" ,"
110+ + "\" src\" :\" " + A_F + " \" ,"
111+ + "\" dst\" :\" " + A_G + " \" ,"
100112 + "\" prov\" :[\" declared\" ],\" weight\" :0}]" ),
101113 "an edge with no call sites behind it should not have been emitted at all" );
102114 }
103115
104116 @ Test
105117 void anEdgeWithNoProvenanceIsRejected () throws IOException {
106118 assertRejected (payload ("\" call_graph\" :[{"
107- + "\" src\" :\" can://java/myapp/A.java/A/f() \" ,"
108- + "\" dst\" :\" can://java/myapp/A.java/A/g() \" ,"
119+ + "\" src\" :\" " + A_F + " \" ,"
120+ + "\" dst\" :\" " + A_G + " \" ,"
109121 + "\" prov\" :[],\" weight\" :1}]" ),
110122 "every edge is attested by at least one analysis" );
111123 }
@@ -115,8 +127,8 @@ void anEdgeProvenanceOutsideTheL2VocabularyIsRejected() throws IOException {
115127 // `ast` is reserved for a future purely-syntactic fallback. Until something produces it, the
116128 // oracle accepting it would let a typo through as a new analysis name.
117129 assertRejected (payload ("\" call_graph\" :[{"
118- + "\" src\" :\" can://java/myapp/A.java/A/f() \" ,"
119- + "\" dst\" :\" can://java/myapp/A.java/A/g() \" ,"
130+ + "\" src\" :\" " + A_F + " \" ,"
131+ + "\" dst\" :\" " + A_G + " \" ,"
120132 + "\" prov\" :[\" ast\" ],\" weight\" :1}]" ),
121133 "L2 provenance is the closed enum [declared, rta]" );
122134 }
@@ -125,16 +137,16 @@ void anEdgeProvenanceOutsideTheL2VocabularyIsRejected() throws IOException {
125137 void anEdgeEndpointThatIsNotACanIdIsRejected () throws IOException {
126138 assertRejected (payload ("\" call_graph\" :[{"
127139 + "\" src\" :\" org.example.A.f()\" ,"
128- + "\" dst\" :\" can://java/myapp/A.java/A/g() \" ,"
140+ + "\" dst\" :\" " + A_G + " \" ,"
129141 + "\" prov\" :[\" declared\" ],\" weight\" :1}]" ),
130142 "endpoints are durable can-ids, not display names" );
131143 }
132144
133145 @ Test
134146 void anEdgeCarryingAnUnknownKeyIsRejected () throws IOException {
135147 assertRejected (payload ("\" call_graph\" :[{"
136- + "\" src\" :\" can://java/myapp/A.java/A/f() \" ,"
137- + "\" dst\" :\" can://java/myapp/A.java/A/g() \" ,"
148+ + "\" src\" :\" " + A_F + " \" ,"
149+ + "\" dst\" :\" " + A_G + " \" ,"
138150 + "\" prov\" :[\" declared\" ],\" weight\" :1,\" line\" :12}]" ),
139151 "a stray key means a producer emitting a fact no consumer was told about" );
140152 }
@@ -144,15 +156,15 @@ void anInProjectIdKeyingTheExternalMapIsRejected() throws IOException {
144156 // The overlay rule: external_symbols may only ever describe symbols outside the project. An
145157 // in-project id here would be a type the tree should have held, silently reclassified.
146158 assertRejected (payload ("\" external_symbols\" :{"
147- + "\" can://java/myapp/src/main/java/org/example/User.java/User/log() \" :{"
159+ + "\" " + USER_LOG + " \" :{"
148160 + "\" kind\" :\" method\" ,\" signature\" :\" log()\" ,\" declaring_type\" :\" org.example.User\" }}" ),
149161 "an in-project can-id is not an external symbol" );
150162 }
151163
152164 @ Test
153165 void anExternalSymbolMissingItsDeclaringTypeIsRejected () throws IOException {
154166 assertRejected (payload ("\" external_symbols\" :{"
155- + "\" can://java/myapp/@external/java.lang.String/valueOf(int) \" :{"
167+ + "\" " + STRING_VALUE_OF + " \" :{"
156168 + "\" kind\" :\" method\" ,\" signature\" :\" valueOf(int)\" }}" ),
157169 "declaring_type is the dotted source spelling the id only carries in binary form" );
158170 }
@@ -161,7 +173,7 @@ void anExternalSymbolMissingItsDeclaringTypeIsRejected() throws IOException {
161173 void anExternalSymbolOfAnUnmodelledKindIsRejected () throws IOException {
162174 // Only call sites mint external symbols, and a call site resolves to a method or a constructor.
163175 assertRejected (payload ("\" external_symbols\" :{"
164- + "\" can://java/myapp/@external/java.lang.String/CASE_INSENSITIVE_ORDER \" :{"
176+ + "\" " + STRING_CASE_ORDER + " \" :{"
165177 + "\" kind\" :\" field\" ,\" signature\" :\" CASE_INSENSITIVE_ORDER\" ,"
166178 + "\" declaring_type\" :\" java.lang.String\" }}" ),
167179 "external symbol kinds are exactly [method, constructor]" );
@@ -170,7 +182,7 @@ void anExternalSymbolOfAnUnmodelledKindIsRejected() throws IOException {
170182 @ Test
171183 void anExternalSymbolCarryingAnUnknownKeyIsRejected () throws IOException {
172184 assertRejected (payload ("\" external_symbols\" :{"
173- + "\" can://java/myapp/@external/java.lang.String/valueOf(int) \" :{"
185+ + "\" " + STRING_VALUE_OF + " \" :{"
174186 + "\" kind\" :\" method\" ,\" signature\" :\" valueOf(int)\" ,"
175187 + "\" declaring_type\" :\" java.lang.String\" ,\" jar\" :\" rt.jar\" }}" ),
176188 "a stray key means a producer emitting a fact no consumer was told about" );
0 commit comments