-
Notifications
You must be signed in to change notification settings - Fork 223
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
analysisScope toJson function #1355
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looking good! I have a few comments. Also, we need to write a test for this new code. You can add it in the AnalysisScopeTest class: https://github.com/wala/WALA/blob/master/core/src/test/java/com/ibm/wala/core/tests/cha/AnalysisScopeTest.java#L21-L21 The test should create an AnalysisScope and then confirm the JSON generated by toJSON()
matches what we expect
|
||
|
||
// import com.google.gson.Gson; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delete these lines
@@ -345,6 +351,30 @@ public String toString() { | |||
return result.toString(); | |||
} | |||
|
|||
public String toJson() { | |||
HashMap<String, Object> res = new HashMap<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this code, let's used LinkedHashMap
instead of HashMap
to ensure a deterministic iteration order https://docs.oracle.com/javase/8/docs/api/java/util/LinkedHashMap.html
@@ -680,4 +680,4 @@ public boolean hasEdge(MethodReference src, MethodReference dst) { | |||
} | |||
}; | |||
} | |||
} | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove this change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still not addressed
@@ -55,4 +55,4 @@ public void testBaseScope() throws IOException, ClassHierarchyException { | |||
ClassLoaderReference.Application, "Ljava/awt/AlphaComposite")), | |||
"found unexpected class"); | |||
} | |||
} | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove this change
@@ -5,4 +5,4 @@ distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip | |||
networkTimeout=10000 | |||
validateDistributionUrl=true | |||
zipStoreBase=GRADLE_USER_HOME | |||
zipStorePath=wrapper/dists | |||
zipStorePath=wrapper/dists |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove this change
String[] exclusions = getExclusions().toString().split("\\|"); | ||
ArrayList<String> arr2 = new ArrayList<>(); | ||
for(int i = 0; i < exclusions.length; i++){ | ||
String word = exclusions[i]; | ||
word = word.replace("(", ""); | ||
word = word.replace(")", ""); | ||
arr2.add(word); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, way to go the extra mile to parse the exclusions!
@@ -680,4 +680,4 @@ public boolean hasEdge(MethodReference src, MethodReference dst) { | |||
} | |||
}; | |||
} | |||
} | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still not addressed
// new FileProvider().getFile("J2SEClassHierarchyExclusions.txt"), | ||
new FileProvider().getFile("GUIExclusions.txt"), | ||
AnalysisScopeTest.class.getClassLoader()); | ||
String exp = "{\"Loaders\":{\"Primordial\":[\"JarFileModule:/opt/homebrew/Cellar/openjdk/21.0.1/libexec/openjdk.jdk/Contents/Home/jmods/java.base.jmod\",\"Nested Jar File:primordial.jar.model\"],\"Extension\":[],\"Application\":[\"JarFileModule:/Users/aakgna/Documents/WALA-Research/WALA/core/build/resources/test/com.ibm.wala.core.testdata_1.0.0.jar\"],\"Synthetic\":[]},\"Exclusions\":[\"java\\\\/awt\\\\/.*\",\"javax\\\\/swing\\\\/.*\",\"sun\\\\/awt\\\\/.*\",\"sun\\\\/swing\\\\/.*\"]}"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking better! But I expect this test will not pass in general, since we have absolute paths in it. So I guess a straightforward string comparison won't work. Here's an alternate approach:
- Call
scope.toJson()
to get the JSON string - Re-parse this String using Gson
- Check that specific parts of the resulting
Map
match what we expect
Can you try that? Let me know if it doesn't make sense
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost there! A couple more comments on the tests
assertEquals(arr2, map.get("Exclusions")); | ||
} | ||
Type type2 = new TypeToken<LinkedHashMap<String, ArrayList<String>>>(){}.getType(); | ||
LinkedHashMap<String, ArrayList<String>> loaders = gson.fromJson(gson.toJson(map.get("Loaders")), type2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here I am confused, why do you need to serialize the data in the map back to JSON and then parse it again? I think you can get rid of this and just use some downcasts to get the data you want out of the map directly
LinkedHashMap<String, Object> map = gson.fromJson(scope.toJson(), type); | ||
System.out.println(map); | ||
if(map.containsKey("Exclusions")) { | ||
String[] exclusions = scope.getExclusions().toString().split("\\|"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we know what is in GUIExclusions.txt
. So I think we can simplify this code. We can just do something like assertEquals(List.of("java\/awt\/.*", "javax\/swing\/.*", "sun\/awt\/.*", "sun\/swing\/.*"), map.get("Exclusions"))
. We can then get rid of this whole loop that re-parses the exclusions string
} | ||
Type type2 = new TypeToken<LinkedHashMap<String, ArrayList<String>>>(){}.getType(); | ||
LinkedHashMap<String, ArrayList<String>> loaders = gson.fromJson(gson.toJson(map.get("Loaders")), type2); | ||
if(loaders.containsKey("Primordial")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again we can simplify this code. We know the contents of wala.testdata.txt
:
Primordial,Java,stdlib,base
Primordial,Java,jarFile,primordial.jar.model
Application,Java,jarFile,com.ibm.wala.core.testdata_1.0.0.jar
So I think we can write assertions like:
- The keys of
loaders
should be exactly"Primordial","Application","Extension","Synthetic"
- Extension and Synthetic should be mapped to empty lists
- Primordial should be mapped to a list of length two. And one of the elements should contain `"primordial.jar.model"
- Application should be mapped to a list of length 1, and that element should contain
"com.ibm.wala.core.testdata_1.0.0.jar"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some more comments
LinkedHashMap<String, ArrayList<String>> loaders = new LinkedHashMap<>(); | ||
for (ClassLoaderReference loader : loadersByName.values()) { | ||
ArrayList<String> arr = new ArrayList<>(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove blank line
AnalysisScope tempScope = | ||
AnalysisScopeReader.instance.readJavaScope( | ||
TestConstants.WALA_TESTDATA, | ||
new FileProvider().getFile("GUIExclusions.txt"), | ||
AnalysisScopeTest.class.getClassLoader()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need to create this temp scope just to test the exclusions. Just skip testing the exclusions here
scope.setExclusions(tempScope.getExclusions()); | ||
String[] stdlibs = WalaProperties.getJ2SEJarFiles(); | ||
Arrays.sort(stdlibs); | ||
int cnt = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment explaining why you are stopping at 5. Also the value 5
should be stored in a local variable and then that variable should be used in multiple places
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But this code would be simpler if you just got rid of the cnt
variable and added everything. Is there any reason to add the limit?
assertThat( | ||
loaders.get("Primordial"), | ||
hasItem( | ||
"JarFileModule:/Users/aakgna/Library/Java/JavaVirtualMachines/corretto-11.0.15/Contents/Home/jmods/java.base.jmod")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check will not pass on other machines. You have the stdlibs
array above. You should use the strings there (which give the full paths to the jars where the tests are running) to check that the right strings are in the JSON.
.get("Primordial") | ||
.get(0) | ||
.contains( | ||
"Java/JavaVirtualMachines/corretto-11.0.15/Contents/Home/jmods/java.base.jmod")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not fully address my comment. Please take the paths directly from the stdlibs
array and check that they match.
new HashSet<>(List.of("Primordial", "Extension", "Application", "Synthetic")); | ||
assertEquals(loaders.keySet(), loaderKeys); | ||
assertEquals(stdlibs.length, loaders.get("Primordial").size()); | ||
assertTrue(loaders.get("Primordial").get(0).contains("/Contents/Home/jmods/java.base.jmod")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is still wrong, and tests are still failing. You need to take the relevant strings from the stdlibs
array for this comparison, rather than just doing get(0)
and comparing to a constant string.
Added a new function to serialize an
AnalysisScope
to JSON format.