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 property based tests to assess load reverses dump #398

Merged
merged 1 commit into from Mar 10, 2018

Conversation

dubzzz
Copy link
Contributor

@dubzzz dubzzz commented Feb 8, 2018

No description provided.

@puzrin
Copy link
Member

puzrin commented Feb 10, 2018

I don't understand why this test is needed. Could you explain?

@dubzzz
Copy link
Contributor Author

dubzzz commented Feb 11, 2018

@puzrin

The idea of this test is to cover (and maybe discover) edge-cases of the js-yaml package we have not think about in the already existing unit-tests. By definition, units cannot cover the range of all possible failures and might miss some complex corner cases. They are based on fixed inputs and expect fixed outputs.

The suggested and complementary approach suggested here, is to add some properties (or contracts) we want to confirm on the package. For the moment the one I introduced check that for any valid object the yaml produced by js-yaml can be read by itself and return the original object.

The strength of property based testing approach is that it does not limit itself to a pre-defined subset of possible entries but goes far beyond by building whatever entry we considered valid. In this example, I defined a valid entry as being all objects whose keys are strings and values are booleans, numbers, strings, nulls, arrays of values or sub-objects. If for any reasons, one of the objects built by the framework made the property failed, the framework will try to reduce it to the minimal object (less keys, smaller values...).

@puzrin
Copy link
Member

puzrin commented Feb 11, 2018

IMHO, in existing context, this looks like adding code "just for fun" - no examples that such tests could help in the past and how those will help in future. I prefer to avoid unnecessary code when possible - more easy to maintain then.

@dubzzz
Copy link
Contributor Author

dubzzz commented Feb 11, 2018

I found a bug in the code of js-yaml using this technic. Indeed js-yaml can produce illegal unicode files. It accepts incomplete surrogate pairs as input.

@dubzzz
Copy link
Contributor Author

dubzzz commented Feb 11, 2018

For the above comment, you can try to build a YAML file from {'\ud800' :''}. It generates an invalid file assuming unicode.

@dubzzz
Copy link
Contributor Author

dubzzz commented Feb 16, 2018

@puzrin Forget about the encoding issue I reported. I enhanced the scope of my property based tests in order to find real issues and found some quite interesting ones when playing on options used by safeDump.

It appears that some yaml values generated by safeDump cannot be read properly by safeLoad.
The following code raises a YAMLException: missed comma between flow collection entries at line 1, column 8

yaml.safeLoad(yaml.safeDump({"":[{"\u0000":""}]},{"condenseFlow":true,"flowLevel":1}));

@puzrin Can you confirm that this is a real bug?

More on this test at https://runkit.com/dubzzz/multiple-properties-for-js-yaml
I really believe that it can find issues not covered by any tests. If you agree it would be nice that we update this pull request in order to cover the edge cases I developed in runkit example.

@puzrin
Copy link
Member

puzrin commented Feb 16, 2018

condenceFlow and flowLevel can not be used in the same time. IMHO it doesn't worth spend time for all possible bad combinations of options.

@dubzzz
Copy link
Contributor Author

dubzzz commented Feb 17, 2018

@puzrin
I tried to extend a bit the scope of the cases covered by my tests (cf. previous runkit link). There is an inconsistency in the behaviour seen when using custom styles for integer type.

const options = {styles:{'!!int':'binary'}};
yaml.safeLoad(yaml.safeDump({toto: 10}, options)); // produces: {toto: 10}
yaml.safeLoad(yaml.safeDump({toto: -10}, options)); // produces: {toto: "0b-1010"}

When negative the integers values produced by js-yaml are read as strings (whereas they are read as integers for positive integers).
Please note that the source code of the test in runkit is a draft and can easily be enhanced.

@dubzzz
Copy link
Contributor Author

dubzzz commented Feb 17, 2018

The right negative binary for -10 should have been -0b1010 not 0b-1010

@puzrin
Copy link
Member

puzrin commented Feb 18, 2018

I agree, that's a real bug of int representer https://github.com/nodeca/js-yaml/blob/master/lib/js-yaml/type/int.js#L159-L164.

Question is - do we need this code in core to maintain forever, or it's a one-time action.

@dubzzz
Copy link
Contributor Author

dubzzz commented Feb 21, 2018

I would say that yes, we should keep some kind of test like this. They ensure non regression and can cover configurations yet uncovered by unit tests. Basically, no one can confirm that no other combination of settings or refactoring would break the code in the future. So yes, I believe it can still be useful to have it.

I am currently trying to revamp the code of the pull request in order to provide a more maintainable code.

@puzrin
Copy link
Member

puzrin commented Feb 22, 2018

Ок. Put it all into 25-dumper-fuzzy.js and i'll merge it.

@dubzzz dubzzz force-pushed the master branch 2 times, most recently from 109f25c to a02e455 Compare February 22, 2018 19:39
@dubzzz
Copy link
Contributor Author

dubzzz commented Feb 22, 2018

Just updated the pull request. Expected failure due to #399

You can see that in the logs of the job:

1) Properties Load from dumped should be the original object:
     Property failed after 1 tests (seed: 1519328411511): [{"":[-1]},{"styles":{"!!int":"binary"}}]
Got error: AssertionError [ERR_ASSERTION]: { '': [ '0b-1' ] } deepStrictEqual { '': [ -1 ] }

Please keep me updated if you want a change in the code.

@puzrin
Copy link
Member

puzrin commented Feb 22, 2018

IMHO it's better to put everything into one file, as i said - more easy to maintain. No need to create complicated files structure in advance.

@dubzzz
Copy link
Contributor Author

dubzzz commented Feb 22, 2018

Ok, I will update my change

suite('Properties', function () {
var directory = path.resolve(__dirname, 'properties');

fs.readdirSync(directory).forEach(function (file) {
Copy link
Member

Choose a reason for hiding this comment

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

Could you put here content of ./properties/identity.js instead of files load? You do too complicated load for single test that will never be extended (with high probability).

@dubzzz
Copy link
Contributor Author

dubzzz commented Mar 9, 2018

Update done, sorry for the delay

@puzrin puzrin merged commit bb7f0cf into nodeca:master Mar 10, 2018
@puzrin
Copy link
Member

puzrin commented Mar 10, 2018

Thanks!

minj added a commit to minj/js-yaml that referenced this pull request Apr 28, 2018
* master: (58 commits)
  Check for leading newlines when determining if block indentation indicator is needed (nodeca#404)
  Add property based tests to assess load reverses dump (nodeca#398)
  3.11.0 released
  Browser files rebuild
  Dumper: fix negative integers in bin/octal/hex formats, close nodeca#399
  support es6 arrow functions, fixes nodeca#389 (nodeca#393)
  Fix typo in README.md (nodeca#373)
  3.10.0 released
  Browser files rebuild
  Add test for astrals dump
  Combine surrogate pairs into one escape sequence when encoding. (nodeca#369)
  Fix condenseFlow for objects (nodeca#371)
  correct spelling mistake (nodeca#367)
  More meaningful error for loader (nodeca#361)
  Fix typo and format code. (nodeca#365)
  3.9.1 released
  Browser files rebuild
  Ensure stack is present for custom errors (fixes nodeca#351) (nodeca#360)
  3.9.0 released
  Browser files rebuild
  ...
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.

None yet

2 participants