-
Notifications
You must be signed in to change notification settings - Fork 292
#2130 MetadataTransfer: single pass over the metadata for wildcard keys #2133
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -152,4 +152,105 @@ void testFilterWithAsterisk() { | |
| } | ||
|
|
||
| static class MyCustomTransferClass extends MetadataTransfer {} | ||
|
|
||
| @Test | ||
| void testWildcardPrefixIsCaseInsensitiveAndSelective() throws MalformedURLException { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good addition, and it pins the case-insensitive prefix behaviour. Nothing covers the caching, which is the part carrying the risk. A test that calls
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added three tests: |
||
| Map<String, Object> conf = new HashMap<>(); | ||
| conf.put(MetadataTransfer.trackPathParamName, false); | ||
| conf.put(MetadataTransfer.trackDepthParamName, false); | ||
| conf.put(MetadataTransfer.metadataTransferParamName, List.of("Cookie.*", "exact")); | ||
| Metadata parentMD = new Metadata(); | ||
| parentMD.addValue("cookie.id", "42"); | ||
| parentMD.addValue("cookies", "not a prefix match"); | ||
| parentMD.addValue("cook", "no"); | ||
| parentMD.addValue("exact", "yes"); | ||
| parentMD.addValue("exactly", "no"); | ||
| Metadata outlinkMD = | ||
| MetadataTransfer.getInstance(conf) | ||
| .getMetaForOutlink( | ||
| "http://www.example.com/outlink.html", | ||
| "http://www.example.com", | ||
| parentMD); | ||
| Assertions.assertEquals(Set.of("cookie.id", "exact"), outlinkMD.keySet()); | ||
| Assertions.assertEquals("42", outlinkMD.getFirstValue("cookie.id")); | ||
| } | ||
|
|
||
| /** Subclass that extends the transfer set after the base configuration, a supported pattern. */ | ||
| static class ExtendingTransferClass extends MetadataTransfer { | ||
| @Override | ||
| protected void configure(Map<String, Object> conf) { | ||
| super.configure(conf); | ||
| mdToTransfer.add("added.*"); | ||
| } | ||
| } | ||
|
|
||
| @Test | ||
| void testSubclassCanExtendTransferSetInConfigure() throws MalformedURLException { | ||
| Map<String, Object> conf = new HashMap<>(); | ||
| conf.put(MetadataTransfer.trackPathParamName, false); | ||
| conf.put(MetadataTransfer.trackDepthParamName, false); | ||
| conf.put( | ||
| MetadataTransfer.metadataTransferClassParamName, | ||
| ExtendingTransferClass.class.getName()); | ||
| conf.put(MetadataTransfer.metadataTransferParamName, List.of("cookie.*")); | ||
| Metadata parentMD = new Metadata(); | ||
| parentMD.addValue("cookie.id", "42"); | ||
| parentMD.addValue("added.key", "yes"); | ||
| parentMD.addValue("other", "no"); | ||
| Metadata outlinkMD = | ||
| MetadataTransfer.getInstance(conf) | ||
| .getMetaForOutlink( | ||
| "http://www.example.com/outlink.html", | ||
| "http://www.example.com", | ||
| parentMD); | ||
| Assertions.assertEquals(Set.of("cookie.id", "added.key"), outlinkMD.keySet()); | ||
| } | ||
|
|
||
| @Test | ||
| void testSameSizeMutationOfTransferSetIsHonoured() throws MalformedURLException { | ||
| Map<String, Object> conf = new HashMap<>(); | ||
| conf.put(MetadataTransfer.trackPathParamName, false); | ||
| conf.put(MetadataTransfer.trackDepthParamName, false); | ||
| conf.put(MetadataTransfer.metadataTransferParamName, List.of("cookie.*")); | ||
| MetadataTransfer mdt = MetadataTransfer.getInstance(conf); | ||
| Metadata parentMD = new Metadata(); | ||
| parentMD.addValue("cookie.id", "42"); | ||
| parentMD.addValue("other", "yes"); | ||
| Assertions.assertEquals( | ||
| Set.of("cookie.id"), | ||
| mdt.getMetaForOutlink( | ||
| "http://www.example.com/outlink.html", | ||
| "http://www.example.com", | ||
| parentMD) | ||
| .keySet()); | ||
| // same size, different content: the compiled filter must not be stale | ||
| mdt.mdToTransfer.remove("cookie.*"); | ||
| mdt.mdToTransfer.add("other"); | ||
| Assertions.assertEquals( | ||
| Set.of("other"), | ||
| mdt.getMetaForOutlink( | ||
| "http://www.example.com/outlink.html", | ||
| "http://www.example.com", | ||
| parentMD) | ||
| .keySet()); | ||
| } | ||
|
|
||
| @Test | ||
| void testNullValueArrayIsSkipped() throws MalformedURLException { | ||
| Map<String, Object> conf = new HashMap<>(); | ||
| conf.put(MetadataTransfer.trackPathParamName, false); | ||
| conf.put(MetadataTransfer.trackDepthParamName, false); | ||
| conf.put(MetadataTransfer.metadataTransferParamName, List.of("cookie.*", "exact")); | ||
| Map<String, String[]> backing = new HashMap<>(); | ||
| backing.put("cookie.id", new String[] {"42"}); | ||
| backing.put("cookie.broken", null); | ||
| backing.put("exact", null); | ||
| Metadata outlinkMD = | ||
| MetadataTransfer.getInstance(conf) | ||
| .getMetaForOutlink( | ||
| "http://www.example.com/outlink.html", | ||
| "http://www.example.com", | ||
| new Metadata(backing)); | ||
| Assertions.assertEquals(Set.of("cookie.id"), outlinkMD.keySet()); | ||
| } | ||
| } | ||
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 detects a size change but not a content change of the same size.
mdToTransferisprotected final Set<String>with mutable contents, so a subclass doingafter the first
filter()call keeps the size and leaves the compiled filter stale. Every outlink from then on carries the wrong metadata, silently.The javadoc on line 205 says the cache is "rebuilt if the set has been modified since (e.g. by a subclass)", which is a stronger claim than the code makes good on.
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.
Fixed in a9578fd.
CompiledFilternow keeps aHashSetsnapshot of the keys it was built from andisForissnapshot.equals(filter), so a same-size content change (remove("depth"); add("mycustom")) rebuilds the compiled form. Javadoc adjusted to describe what the code does. TesttestSameSizeMutationOfTransferSetIsHonouredreproduces the exact scenario and failed on the previous revision.