Skip to content

analysisScope toJson function#1355

Merged
msridhar merged 29 commits intowala:masterfrom
aakgna:master
Mar 7, 2024
Merged

analysisScope toJson function#1355
msridhar merged 29 commits intowala:masterfrom
aakgna:master

Conversation

@aakgna
Copy link
Copy Markdown
Contributor

@aakgna aakgna commented Jan 4, 2024

Added a new function to serialize an AnalysisScope to JSON format.

@msridhar msridhar self-requested a review January 22, 2024 20:42
Copy link
Copy Markdown
Member

@msridhar msridhar left a 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

Comment on lines +60 to +62


// import com.google.gson.Gson;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete these lines

}

public String toJson() {
HashMap<String, Object> res = new HashMap<>();
Copy link
Copy Markdown
Member

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

};
}
}
} No newline at end of file
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this change

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still not addressed

"found unexpected class");
}
}
} No newline at end of file
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this change

validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
zipStorePath=wrapper/dists No newline at end of file
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this change

Comment on lines +365 to +372
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);
}
Copy link
Copy Markdown
Member

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!

@github-actions
Copy link
Copy Markdown

github-actions bot commented Jan 30, 2024

Test Results

  572 files  ± 0    572 suites  ±0   3h 37m 54s ⏱️ + 29m 35s
  734 tests + 2    717 ✅ + 2  17 💤 ±0  0 ❌ ±0 
3 554 runs  +10  3 467 ✅ +10  87 💤 ±0  0 ❌ ±0 

Results for commit efad143. ± Comparison against base commit 0e3068a.

♻️ This comment has been updated with latest results.

};
}
}
} No newline at end of file
Copy link
Copy Markdown
Member

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\\\\/.*\"]}";
Copy link
Copy Markdown
Member

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:

  1. Call scope.toJson() to get the JSON string
  2. Re-parse this String using Gson
  3. 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

Copy link
Copy Markdown
Member

@msridhar msridhar left a 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);
Copy link
Copy Markdown
Member

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("\\|");
Copy link
Copy Markdown
Member

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")) {
Copy link
Copy Markdown
Member

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"

Copy link
Copy Markdown
Member

@msridhar msridhar left a 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<>();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove blank line

Comment on lines +106 to +110
AnalysisScope tempScope =
AnalysisScopeReader.instance.readJavaScope(
TestConstants.WALA_TESTDATA,
new FileProvider().getFile("GUIExclusions.txt"),
AnalysisScopeTest.class.getClassLoader());
Copy link
Copy Markdown
Member

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;
Copy link
Copy Markdown
Member

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

Copy link
Copy Markdown
Member

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"));
Copy link
Copy Markdown
Member

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"));
Copy link
Copy Markdown
Member

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"));
Copy link
Copy Markdown
Member

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.

@msridhar msridhar merged commit ae3b95d into wala:master Mar 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants