Skip to content
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

Add tests from JSONTestSuite #140

Merged
merged 1 commit into from May 24, 2024
Merged

Add tests from JSONTestSuite #140

merged 1 commit into from May 24, 2024

Conversation

gavlyukovskiy
Copy link
Collaborator

@gavlyukovskiy gavlyukovskiy commented May 4, 2024

This PR adds all tests from JSONTestSuite. That suite has 3 types of tests:

  • y_* are valid JSONs
  • i_* are invalid JSONs that are allowed to be parsed, usually some large numbers and/or invalid UTF-8 sequences
  • n_* are invalid JSONs, for this the normal parser should fail, however we can process all of them except 2 that have 100k nesting level (P.S. Don't try opening them in IDEA πŸ˜„)

I've copied all of them to our repository and established following test cases

mustPassSuiteWithNoopMaskerShouldBeEquivalentToJackson

y_* tests must pass. I'm using ValueMaskers.withRawValueFunction(value -> value) as a more complicated noop masker to make sure that we always correctly track values, transform them to strings and back to bytes. The results of this are equivalent when parsed by Jackson

mayPassSuiteWithNoopMaskerShouldNotFail

i_* tests must not fail with and ideally should be equivalent to how Jackson parses it (if it can). There are 4 exceptions when java.lang.String treats invalid UTF-8 characters differently than Jackson does

mustFailSuiteWithNoopMaskerShouldOnlyFailWithInvalidJsonException

n_* tests must fail for a normal JSON parser, however we allow it not to fail, but if it does fail, then it must be with InvalidJsonException. With ValueMaskers.withRawValueFunction (or default masking options) there are only 2 test cases that are failing due to internal StackOverFlowError.

shouldMaskAllTestCasesPredictably

For all test files (including n_*) I've simply asserted the masker json we currently produce.

mustPassSuiteWithNoopTextFunction

Verifies that all test files that contain correct UTF-8 sequences we properly decode it in withTextValueFunction. There are 26 i_* test files where we fail on converting invalid sequences.

For the withTextValueFunction function the question is whether we should continue to fail on those 26 test cases or take the behavior of java.lang.String of converting most invalid sequences into οΏ½ and passing that to the user provided function?

Fixes

This PR has couple of fixes for cases when we get out of bounds or throw internal exception instead of InvalidJsonException. All of the fixes only apply to n_* and i_* test cases, nothing critical was found during the testing πŸ˜ƒ

Hard decisions time!

The main problem is what to do with n_* test cases?

The main problem is that we're not actually parsing the values so we do not reject things like invalid numbers or invalid escapes (except for withTextValueFunction. We also do not fail on invalid json structures - for example in arrays we don't strictly need to see a comma and ignore anything unknown and mask values if we detect them. With that for most of the test cases we actually mask them in more or less predictable ways, for example

  • ["" -> ["***" (n_array_unclosed.json)
  • [ , ""] -> [ , "***"] (n_array_missing_value.json)

However some test cases are leaking information or giving weird results

  • abc -> abc (n_string_single_string_no_double_quotes.json) when string doesn't have quotes then we simply leave it as is
  • ['single quote'] -> ['single quo"&&&" (n_string_single_quote.json) we ignore the value started with a single quote and accidentally think that we've found a boolean to mask

In shouldMaskAllTestCasesPredictably I've asserted the current status, so it would be useful to go over them and decide whether we should do anything special about each one of those.

Closes #121

Copy link

github-actions bot commented May 4, 2024

Note

These results are affected by shared workloads on GitHub runners. Use the results only to detect possible regressions, but always rerun on more stable machine before making any conclusions!

Benchmark results (pull-request, 02e873c)

Benchmark                                                          (characters)  (jsonPath)  (jsonSize)  (maskedKeyProbability)   Mode  Cnt        Score       Error   Units
BaselineBenchmark.countBytes                                            unicode         N/A         1kb                     0.1  thrpt    4  2597878.760 Β± 55214.880   ops/s
BaselineBenchmark.countBytes:gc.alloc.rate.norm                         unicode         N/A         1kb                     0.1  thrpt    4       β‰ˆ 10⁻⁴                B/op
BaselineBenchmark.jacksonParseAndMask                                   unicode         N/A         1kb                     0.1  thrpt    4    29691.626 Β±   405.803   ops/s
BaselineBenchmark.jacksonParseAndMask:gc.alloc.rate.norm                unicode         N/A         1kb                     0.1  thrpt    4    65360.007 Β±     0.009    B/op
BaselineBenchmark.jacksonParseOnly                                      unicode         N/A         1kb                     0.1  thrpt    4    51922.189 Β±  1330.396   ops/s
BaselineBenchmark.jacksonParseOnly:gc.alloc.rate.norm                   unicode         N/A         1kb                     0.1  thrpt    4    24352.004 Β±     0.001    B/op
BaselineBenchmark.regexReplace                                          unicode         N/A         1kb                     0.1  thrpt    4     5135.173 Β±   158.267   ops/s
BaselineBenchmark.regexReplace:gc.alloc.rate.norm                       unicode         N/A         1kb                     0.1  thrpt    4    61656.036 Β±     0.003    B/op
JsonMaskerBenchmark.jsonMaskerBytes                                     unicode       false         1kb                     0.1  thrpt    4   443265.436 Β±  7721.031   ops/s
JsonMaskerBenchmark.jsonMaskerBytes:gc.alloc.rate.norm                  unicode       false         1kb                     0.1  thrpt    4     2232.000 Β±     0.001    B/op
JsonMaskerBenchmark.jsonMaskerBytes                                     unicode        true         1kb                     0.1  thrpt    4   633252.596 Β± 17046.233   ops/s
JsonMaskerBenchmark.jsonMaskerBytes:gc.alloc.rate.norm                  unicode        true         1kb                     0.1  thrpt    4     1280.000 Β±     0.001    B/op
JsonMaskerBenchmark.jsonMaskerString                                    unicode       false         1kb                     0.1  thrpt    4   242061.367 Β±  2599.519   ops/s
JsonMaskerBenchmark.jsonMaskerString:gc.alloc.rate.norm                 unicode       false         1kb                     0.1  thrpt    4    10136.001 Β±     0.001    B/op
JsonMaskerBenchmark.jsonMaskerString                                    unicode        true         1kb                     0.1  thrpt    4   229563.933 Β±  2180.684   ops/s
JsonMaskerBenchmark.jsonMaskerString:gc.alloc.rate.norm                 unicode        true         1kb                     0.1  thrpt    4    10312.001 Β±     0.001    B/op
ValueMaskerBenchmark.maskWithRawValueFunction                           unicode         N/A         1kb                     0.1  thrpt    4   684465.685 Β± 35260.523   ops/s
ValueMaskerBenchmark.maskWithRawValueFunction:gc.alloc.rate.norm        unicode         N/A         1kb                     0.1  thrpt    4     1592.000 Β±     0.001    B/op
ValueMaskerBenchmark.maskWithStatic                                     unicode         N/A         1kb                     0.1  thrpt    4   771495.896 Β± 31878.538   ops/s
ValueMaskerBenchmark.maskWithStatic:gc.alloc.rate.norm                  unicode         N/A         1kb                     0.1  thrpt    4     1232.000 Β±     0.001    B/op
ValueMaskerBenchmark.maskWithTextValueFunction                          unicode         N/A         1kb                     0.1  thrpt    4   603895.151 Β± 15617.026   ops/s
ValueMaskerBenchmark.maskWithTextValueFunction:gc.alloc.rate.norm       unicode         N/A         1kb                     0.1  thrpt    4     1880.000 Β±     0.001    B/op

Benchmark results (master, 7bc09ac)

Benchmark                                                          (characters)  (jsonPath)  (jsonSize)  (maskedKeyProbability)   Mode  Cnt        Score        Error   Units
BaselineBenchmark.countBytes                                            unicode         N/A         1kb                     0.1  thrpt    4  2595251.864 Β± 116163.735   ops/s
BaselineBenchmark.countBytes:gc.alloc.rate.norm                         unicode         N/A         1kb                     0.1  thrpt    4       β‰ˆ 10⁻⁴                 B/op
BaselineBenchmark.jacksonParseAndMask                                   unicode         N/A         1kb                     0.1  thrpt    4    29792.200 Β±    881.748   ops/s
BaselineBenchmark.jacksonParseAndMask:gc.alloc.rate.norm                unicode         N/A         1kb                     0.1  thrpt    4    65184.006 Β±      0.004    B/op
BaselineBenchmark.jacksonParseOnly                                      unicode         N/A         1kb                     0.1  thrpt    4    51625.098 Β±   2503.166   ops/s
BaselineBenchmark.jacksonParseOnly:gc.alloc.rate.norm                   unicode         N/A         1kb                     0.1  thrpt    4    24352.004 Β±      0.001    B/op
BaselineBenchmark.regexReplace                                          unicode         N/A         1kb                     0.1  thrpt    4     5111.192 Β±     74.164   ops/s
BaselineBenchmark.regexReplace:gc.alloc.rate.norm                       unicode         N/A         1kb                     0.1  thrpt    4    61656.035 Β±      0.009    B/op
JsonMaskerBenchmark.jsonMaskerBytes                                     unicode       false         1kb                     0.1  thrpt    4   447551.817 Β±  10121.186   ops/s
JsonMaskerBenchmark.jsonMaskerBytes:gc.alloc.rate.norm                  unicode       false         1kb                     0.1  thrpt    4     2232.000 Β±      0.001    B/op
JsonMaskerBenchmark.jsonMaskerBytes                                     unicode        true         1kb                     0.1  thrpt    4   676273.054 Β±   9697.752   ops/s
JsonMaskerBenchmark.jsonMaskerBytes:gc.alloc.rate.norm                  unicode        true         1kb                     0.1  thrpt    4     1280.000 Β±      0.001    B/op
JsonMaskerBenchmark.jsonMaskerString                                    unicode       false         1kb                     0.1  thrpt    4   241992.606 Β±  10176.033   ops/s
JsonMaskerBenchmark.jsonMaskerString:gc.alloc.rate.norm                 unicode       false         1kb                     0.1  thrpt    4    10136.001 Β±      0.001    B/op
JsonMaskerBenchmark.jsonMaskerString                                    unicode        true         1kb                     0.1  thrpt    4   260060.687 Β±   6548.330   ops/s
JsonMaskerBenchmark.jsonMaskerString:gc.alloc.rate.norm                 unicode        true         1kb                     0.1  thrpt    4    10312.001 Β±      0.001    B/op
ValueMaskerBenchmark.maskWithRawValueFunction                           unicode         N/A         1kb                     0.1  thrpt    4   662720.760 Β±  11135.643   ops/s
ValueMaskerBenchmark.maskWithRawValueFunction:gc.alloc.rate.norm        unicode         N/A         1kb                     0.1  thrpt    4     1592.000 Β±      0.001    B/op
ValueMaskerBenchmark.maskWithStatic                                     unicode         N/A         1kb                     0.1  thrpt    4   743197.178 Β±  33867.771   ops/s
ValueMaskerBenchmark.maskWithStatic:gc.alloc.rate.norm                  unicode         N/A         1kb                     0.1  thrpt    4     1232.000 Β±      0.001    B/op
ValueMaskerBenchmark.maskWithTextValueFunction                          unicode         N/A         1kb                     0.1  thrpt    4   587460.446 Β±  27832.634   ops/s
ValueMaskerBenchmark.maskWithTextValueFunction:gc.alloc.rate.norm       unicode         N/A         1kb                     0.1  thrpt    4     1880.000 Β±      0.001    B/op

Copy link

sonarcloud bot commented May 4, 2024

@gavlyukovskiy
Copy link
Collaborator Author

@Breus looks like that badge is going to get a little bit more impressive πŸ˜„
image

Copy link
Collaborator

@donavdey donavdey left a comment

Choose a reason for hiding this comment

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

The main problem is what to do with n_* test cases?

I'd suggest to clearly claim in the docs that the masker is not a RFC 8259 compliant JSON parser, so the output for non-valid JSONs may be unpredictable.

Copy link
Owner

@Breus Breus left a comment

Choose a reason for hiding this comment

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

LGTM. Let's address the invalid input handling (? vs throwing exception) in a different PR. Not too big of a deal

@Breus Breus merged commit ec96ef1 into master May 24, 2024
4 checks passed
@Breus Breus deleted the json-test-suite branch May 24, 2024 13:45
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.

Integrate JSONTestSuite
3 participants