GithubHelp home page GithubHelp logo

lithium's Introduction

Task Status codecov Matrix PyPI

Using Lithium

Lithium is an automated testcase reduction tool developed by Jesse Ruderman.

Most of what you need to know to use Lithium is in one of these pages:

Lithium's algorithm

By default, Lithium uses a clever algorithm that's efficient at reducing most large testcases. For a testcase with 2048 lines, it will try removing each chunk of size 1024, permanently removing it if it is still 'interesting'. It then does the same for each chunk of size 512, then 256, all the way down to chunks of size 1. It then does as many additional rounds at chunk size 1 as necessary until it completes a round without removing anything, at which point the file is 1-minimal (removing any single line from the file makes it 'uninteresting').

If n is the size of the testcase and m is the size of the 1-minimal testcase found by Lithium, then Lithium usually performs O(m ⋅ lg(n)) tests with a total test size of O(m ⋅ n). See the analysis of Lithium's algorithm for more information and proofs.

To keep m small, make sure Lithium's smallest removals won't introduce fatal syntax errors into the file it is trying to reduce. For example, don't use --char when trying to reduce a long sequence of JavaScript statements, and don't feed XHTML to Lithium. (Convert it to HTML first and let Firefox's tag-soup parser sort out the invalidity, or use serializeDOMAsScript.)

Command line syntax

pip install lithium-reducer
python -m lithium [options] interestingness-test.py [arguments for interestingness test]

Command line options

--testcase=filename
Tells Lithium which file to reduce. By default, it will assume the last argument to the interestingness test is the file to reduce.
--char (-c)
By default, Lithium treats lines as atomic units. This is great if each line is a JavaScript statement, but sometimes you want to go further. Use this option to tell Lithium to treat the file as a sequence of characters instead of a sequence of lines.
--strategy=[check-only,minimize,minimize-balanced,replace-properties-by-globals,replace-arguments-by-globals,minimize-around]
"minimize" is the default, the algorithm described above. "check-only" tries to run Lithium to determine interestingness, without reduction. For the other strategies, check out this GitHub PR.
--repeat=[always, last, never].
By default, Lithium only repeats at the same chunk size if it just finished the last round (e.g. chunk size 1). You can use --repeat=always to tell it to repeat any chunk size if something was removed during the round, which can be useful for non-deterministic testcases or non-monotonic situations. You can use --repeat=never to tell it to exit immediately after a single round at the last chunk size, which can save a little time at the risk of leaving a little bit extra in the file.
--max=n. default: about half of the file.
--min=n. default: 1.
What chunk sizes to test. Must be powers of two. --max is useful if you're restarting Lithium after it has already gone through a few rounds. --min is useful if you're reducing HTML and want to do the final by hand.
--chunk-size=n
Shortcut for "repeat=never, min=n, max=n". --chunk-size=1 is a quick way to determine whether a file is 1-minimal, for example after making a change that you think might make some lines unnecessary.

Hints

If you find a non-deterministic bug, don't despair. Lithium will do fine as long as you make the bug happen at least 70% of the time. You can repeat the test either within the application, by adding a loop or reload in the testcase (outside of the DDBEGIN/DDEND markers!), or outside of the application, by adding a loop to the "interestingness test" script.

Requirements

Lithium is written in Python and requires Python 3.5+.

Credits

lithium's People

Contributors

dkasak avatar jruderman avatar jschwartzentruber avatar mozilla-github-standards avatar nbp avatar nth10sd avatar orenyomtov avatar pyoor avatar sei-eschwartz avatar tysmith avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lithium's Issues

Allow repeat interestingness test to support a min_crashes setting

An interestingness test in another of our repos support a min_crashes setting when run in repeat mode. That is, Lithium will only consider a testcase interesting if it reproduces at least x times in y tries.

Currently the repeat interestingness test in Lithium shortcuts if it reproduces once in y tries.

TestcaseJsStr should ignore unmatched quote characters while scanning

When reducing a testcase with TestcaseJsStr containing broken strings, this assertion is hit:

AssertionError: Unexpected EOF looking for end of string (')

A better approach would be to continue parsing as though the starting string were not there. Eg.

'abc', "'123'

Currently this hits the above assertion. I propose to parse it as follows (ignoring the unmatched "):

'
a
b
c
', "'
1
2
3
'

Make chunk moving an option

Currently, chunk moving is experimental, and is prevented from running by a boolean statement. (not commented out to keep the linters running on it)

We could turn it into an option as a start, while still labelling it experimental.

The "outputs" interestingness test is not working in Python 3+

I installed lithium in a virtualenv for Python 3 on master (without any of our imports patches) and found that the "outputs" interestingness test is not working as expected:

$ touch temp.js
$ testVenv/bin/python -m lithium outputs --timeout=2 temp.js ls temp.js
Intermediate files will be stored in tmp11/.
The original testcase has 0 lines.
Checking that the original testcase is 'interesting'...
Traceback (most recent call last):
  File "/usr/lib/python3.5/runpy.py", line 184, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib/python3.5/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/home/gkwubu/aa20170728/testVenv/lib/python3.5/site-packages/lithium/__main__.py", line 13, in <module>
    main()
  File "/home/gkwubu/aa20170728/testVenv/lib/python3.5/site-packages/lithium/lithium/lithium.py", line 1322, in main
    exit(Lithium().main())
  File "/home/gkwubu/aa20170728/testVenv/lib/python3.5/site-packages/lithium/lithium/lithium.py", line 1105, in main
    return self.run()
  File "/home/gkwubu/aa20170728/testVenv/lib/python3.5/site-packages/lithium/lithium/lithium.py", line 1121, in run
    result = self.strategy.main(self.testcase, self.interesting, self.testcaseTempFilename)
  File "/home/gkwubu/aa20170728/testVenv/lib/python3.5/site-packages/lithium/lithium/lithium.py", line 248, in main
    if not interesting(testcase, writeIt=False):
  File "/home/gkwubu/aa20170728/testVenv/lib/python3.5/site-packages/lithium/lithium/lithium.py", line 1276, in interesting
    inter = self.conditionScript.interesting(self.conditionArgs, tempPrefix)
  File "/home/gkwubu/aa20170728/testVenv/lib/python3.5/site-packages/lithium/lithium/../interestingness/outputs.py", line 39, in interesting
    fileIngredients.fileContains(tempPrefix + "-out.txt", searchFor, regexEnabled)[0] or
  File "/home/gkwubu/aa20170728/testVenv/lib/python3.5/site-packages/lithium/lithium/../interestingness/fileIngredients.py", line 16, in fileContains
    return fileContainsStr(f, s, verbose=vb), s
  File "/home/gkwubu/aa20170728/testVenv/lib/python3.5/site-packages/lithium/lithium/../interestingness/fileIngredients.py", line 23, in fileContainsStr
    if line.find(s) != -1:
TypeError: a bytes-like object is required, not 'str'

Lithium should be tested continuously

We should be running tests on a continuous basis using Travis-CI+Appveyor or alternatives.
This depends on the tests added in #14, and could also check the coding style defined in #15.

Add venv tests

#36 was split off into #50 for the interestingness script tests, so filing this for the venv test addition portion.

How does one use a built-in interestingness test?

I'm having trouble using a built-in interestingness test crashes.py. What am I doing wrong?

[eschwartz@pd2 lithium]$ python -m lithium ~/.local/lib/python2.7/site-packages/lithium/interestingness/crashes.py
Traceback (most recent call last):
  File "/usr/lib64/python2.7/runpy.py", line 162, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib64/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/data/shared/home/eschwartz/.local/lib/python2.7/site-packages/lithium/__main__.py", line 13, in <module>
    main()
  File "/home/eschwartz/.local/lib/python2.7/site-packages/lithium/reducer.py", line 1517, in main
    exit(Lithium().main())
  File "/home/eschwartz/.local/lib/python2.7/site-packages/lithium/reducer.py", line 1293, in main
    self.processArgs(args)
  File "/home/eschwartz/.local/lib/python2.7/site-packages/lithium/reducer.py", line 1437, in processArgs
    self.conditionScript = rel_or_abs_import(extra_args[0])
  File "/home/eschwartz/.local/lib/python2.7/site-packages/lithium/interestingness/utils.py", line 140, in rel_or_abs_import
    return importlib.import_module(module)
  File "/usr/lib64/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
  File "/data/shared/home/eschwartz/.local/lib/python2.7/site-packages/lithium/interestingness/crashes.py", line 18, in <module>
    from . import timed_run
ValueError: Attempted relative import in non-package

Better highlight DDBEGIN/DDEND in the documentation

DDBEGIN/DDEND are not mentioned at all in the command line help, and only mentioned briefly as a reduction hint on the README.md file at https://github.com/MozillaSecurity/lithium/#hints

The command line help actually suggests to read using-for-firefox.md which again mentions DDBEGIN/DDEND briefly at https://github.com/MozillaSecurity/lithium/blob/master/src/lithium/docs/using-for-firefox.md#preparing-the-testcase

I believe this DDBEGIN/DDEND feature is a nice trick to help reduction and I believe it deserves more visibility. What documenting it in the command line help or main README instead of the using-for-firefox doc? At Igalia we have successfully been using lithium to reduce testcases in other browsers, including Chromium and WebKit (thanks BTW!) and one may easily overlook the "using-for-firefox" help (actually, the command line help should probably refer to something else than using-for-firefox.md but I guess that's a separate issue).

Support for parallel reduction

It seems like it'd be nice to have support for running reductions in parallel.

There are some disadvantages, so this should definitely be opt-in. One issue is that there may be dependencies between chunks which need to be handled in some fashion. When you have a file with chunks like this:

A
B
C
D

It may be that you can successfully remove C only if you have previously removed A, or that you will succeed in removing D only if you did not already remove B. If you run the reductions where you remove A, B, C, and D in parallel, this will produce nondeterministic results.

Nondeterministic results would be acceptable for a lot of use cases, though, so I think there'd be value in supporting the feature.

Would the other users of lithium find this useful? Has anyone taken a look at doing this already?

crashes interestingness goes down useless path

I have an application with two crash paths, where one is interesting (for me) and the other not. When reducing the test case, I end up with a small file triggering the uninteresting part - any bright ideas on how to mark a specific crash type (stack overrun, div by 0 or similar) as not interesting without implementing a full debugger?

pkg_resources is not supported by Python 3.12

Traceback (most recent call last):
  File "<frozen runpy>", line 189, in _run_module_as_main
  File "<frozen runpy>", line 148, in _get_module_details
  File "<frozen runpy>", line 112, in _get_module_details
  File "/home/user/workspace/venvs/dev/lib/python3.12/site-packages/lithium/__init__.py", line 6, in <module>
    from .reducer import Lithium
  File "/home/user/workspace/venvs/dev/lib/python3.12/site-packages/lithium/reducer.py", line 14, in <module>
    import pkg_resources
ModuleNotFoundError: No module named 'pkg_resources'

Add a way to preprocess chunks before attempting to reduce the test case

It'd be great to be able to provide, in an addition to an "interestingness" test, a chunk preprocessing strategy.

Here's what I'm interested in using it for:

What I observe when I'm using lithium is that at large chunk sizes, it's often the case that a chunk could have been removed (i.e., the file was interesting without it) except that a poorly placed chunk boundary led to a syntax error. Since removing large chunks early on drastically reduces runtimes, I'd really like to help those large chunk removals succeed. It seems to me that a small degree of knowledge about the syntax of the file that lithium is processing would go a long way.

What I plan to do as a first attempt is to process the input file with pygments, which is a Python library for syntax highlighting. The syntax highlighting definitions are mostly implemented using regular expressions, but a stack is included to support grammars which involve nesting. Essentially, pygments provides simple parsers for a very large number of programming languages.

Most of the information that pygments produces is specific to a particular file format, but what I find interesting is the stack. I'd expect that if a chunk has exactly the same stack at the beginning and the end (i.e., we haven't popped the original elements in the stack off, and we have popped off everything that's been added in the interim) then it's much more likely to be syntactically correct and hence removable. So, given this information, we can move around the chunk boundaries in a way that should help us remove more large chunks.

The pygments stuff is speculative at this point, and it may be a bit much to include in upstream lithium (though I'd be happy to fold it in if there's interest). I think that offering a general way to preprocess the chunks selected for each pass in this fashion would probably be quite useful in all sorts of ways, though.

Does that sound like a feature you'd like to include?

Coding style should be defined and checkable

Pylint gives a lot of warnings:

+-----------+-------+
|type       |number |
+===========+=======+
|convention |396    |
+-----------+-------+
|refactor   |10     |
+-----------+-------+
|warning    |40     |
+-----------+-------+
|error      |1      |
+-----------+-------+

Messages
--------

+------------------------------+------------+
|message id                    |occurrences |
+==============================+============+
|invalid-name                  |316         |
+------------------------------+------------+
|bad-whitespace                |40          |
+------------------------------+------------+
|global-variable-not-assigned  |24          |
+------------------------------+------------+
|missing-docstring             |22          |
+------------------------------+------------+
|line-too-long                 |12          |
+------------------------------+------------+
|global-statement              |7           |
+------------------------------+------------+
|unused-variable               |5           |
+------------------------------+------------+
|too-many-locals               |4           |
+------------------------------+------------+
|too-many-statements           |3           |
+------------------------------+------------+
|too-many-branches             |3           |
+------------------------------+------------+
|superfluous-parens            |2           |
+------------------------------+------------+
|anomalous-backslash-in-string |2           |
+------------------------------+------------+
|wrong-import-position         |1           |
+------------------------------+------------+
|using-constant-test           |1           |
+------------------------------+------------+
|unneeded-not                  |1           |
+------------------------------+------------+
|trailing-whitespace           |1           |
+------------------------------+------------+
|too-many-lines                |1           |
+------------------------------+------------+
|redefined-builtin             |1           |
+------------------------------+------------+
|import-error                  |1           |
+------------------------------+------------+

Global evaluation
-----------------
Your code has been rated at 3.91/10 (previous run: 3.91/10, +0.00)

We should define a desired coding style for Lithium in a pylintrc (or alternative) and fix all violations, adding exceptions where needed. The same config should likely be used in other funfuzz based projects (jsfunfuzz/autobisect/DOMFuzz).

No progress after character reduction

After I hit character reduction on lithium, there is no progress...:(

Tested on Ubuntu 16.04

After this message was displayed, nothing happened(waited for a hour)... line reduction was succeeded, so I assume my install is fine.


Running character reduction...

/home/kaze/lithium/lithium/lithium.py --char /home/kaze/funfuzz/js/jsInteresting.py --minlevel=5 --timeout=20 mozilla-central shell-cache/js-64-dm-linux-cc65f9233e5b/js-64-dm-linux-cc65f9233e5b --fuzzing-safe --non-writable-jitcode --gc-zeal=8 --no-sse3 --no-baseline --ion-offthread-compile=off --ion-eager --ion-edgecase-analysis=off --ion-limit-script-size=off wtmp2/w16-reduced.js
Preparing to run Lithium, log file wtmp2/w16-5-lines-lith-out.txt
/usr/bin/python -u /home/kaze/funfuzz/util/../../lithium/lithium/lithium.py --tempdir=wtmp2/w16-5-lines-lith-tmp --char /home/kaze/funfuzz/js/jsInteresting.py --minlevel=5 --timeout=20 mozilla-central shell-cache/js-64-dm-linux-cc65f9233e5b/js-64-dm-linux-cc65f9233e5b --fuzzing-safe --non-writable-jitcode --gc-zeal=8 --no-sse3 --no-baseline --ion-offthread-compile=off --ion-eager --ion-edgecase-analysis=off --ion-limit-script-size=off wtmp2/w16-reduced.js


My temp folder was getting bigger and bigger... I think lithium is looping forever

This is my log file. Am I missing something?

w16-5-lines-lith-out.txt

Add ability to always treat the test case as interesting initially

The ability to specify that lithium should treat the test case as interesting initially (before any chunk removals are done, regardless of whether it is actually interesting or not) would be a nice addition.

It would allow lithium to act as a fuzzer, as explained in the Reducers are Fuzzers blog post.

Some use cases:

  • It often happens that I have a hunch that a certain part of the code is broken, but I'm unable to trigger the faulty behaviour with a test case. What sometimes works is writing a test case that exercises this part of the code but is uninteresting (e.g. doesn't crash) and then letting lithium crashes run while forcing it to treat the case as interesting.
  • A fix for a bug had been deployed but you have a hunch that the fix isn't a proper one and just fixes it for some particular test case. This would allow you to uncover potential related test cases that still trigger the bug.

I'm not sure how to implement this best in lithium, though. Any suggestions? For now, I've just hacked together a non-crashes interestingness test for my personal use. It behaves exactly as crashes, except it forces the test case to be interesting in the initial run. The downside of this approach is that you can't reuse this code with other interestingness tests for which you might want to turn this behaviour on.

Fixate linter versions

We'll need to fixate linter versions to prevent new linter checks from failing our CI tests if we are not really ready for them.

Lithium throws in --char mode

python -u lithium.py -c crashes --timeout=3 ./js-dbg-64-dm-clang-darwin-2f9e69c982f1 --fuzzing-safe --no-threads --ion-eager --no-baseline testcase.js does not seem to work.

`usage: ./lithium.py [options] condition [condition options] file-to-reduce

example: ./lithium.py crashes 120 ~/tracemonkey/js/src/debug/js -j a.js
Lithium will reduce a.js subject to the condition that the following
crashes in 120 seconds:
~/tracemonkey/js/src/debug/js -j a.js
lithium.py: error: unrecognized arguments: --timeout=3`

Removing -c does work. Moreover, removing --timeout=3 throws:

Failed to import: js-dbg-64-dm-clang-darwin-2f9e69c982f1
From: /Users/skywalker/lithium/interestingness/ximport.pyc
No module named js-dbg-64-dm-clang-darwin-2f9e69c982f1
Traceback (most recent call last):
File "/Users/skywalker/lithium/lithium/lithium.py", line 402, in
if processOptions():
File "/Users/skywalker/lithium/lithium/lithium.py", line 180, in processOptions
conditionScript = ximport.importRelativeOrAbsolute(extra_args[0])
File "/Users/skywalker/lithium/interestingness/ximport.py", line 21, in importRelativeOrAbsolute
module = import(f)
ImportError: No module named js-dbg-64-dm-clang-darwin-2f9e69c982f1

Consider renaming some "lithium" names, e.g. of the subdirectory/file itself

We use lots of the lithium name everywhere. It is used at least in:

  • GitHub repo (Python package) name
  • Subdirectory name, adjacent to interestingness
  • The python filename lithium.py itself
  • Lithium class object
    • Easier to differentiate due to capitalisation
  • lithium logger in lithium.py
    • Easier to differentiate, but we could call it lithLog or something to make grepping for the word lithium less painful to scroll through

This made issues with the import system (e.g. PR #28) extremely hard to debug, due to confusion over whether a lithium word is a package/top-level file/module/directory. Even if they were all different, it would already have been complex due to Python packaging being hard to get right.

I would like to at least consider renaming the lithium subdirectory to core, and probably lithium.py to lithreduce.py or lithreducer.py as well. We might as well do this around the time we need to update our other repos to support #28 anyway, due to the need to move away from running lithium python files directly, instead importing lithium and running it as a module in funfuzz, for example.

@jschwartzentruber, thoughts?

problem to use lithium in windows

Hi,

i'm trying use lithium on windows to reduce a testcase html crash of some app.

C:\Python27>python.exe -m lithium outputs --timeout=5 --timeout=120 "ASSERTION: index out of range" C:\app.exe testcase.html
Intermediate files will be stored in tmp3.
The original testcase has 822 lines.
Checking that the original testcase is 'interesting'...

The first error, which maybe I make is that I put "ASSERTION: index out of range", I do not understand that argument or that I should put according to the app or the file to be tested.

Currently the result is that the windbg is open with the crash and nothing else happens, except that it closes it by hand (the windbg) there ends the program.

Intermediate files will be stored in tmp3.
The original testcase has 822 lines.
Checking that the original testcase is 'interesting'...
Exit status: TIMED OUT (409.658 seconds)
Lithium result: the original testcase is not 'interesting'!
Tests performed: 1
Test total: 822 lines

interestingness.timed_run uses SIGKILL to terminate process

Many of the interestingness scripts use timed_run to implement timeout support. When timeout occurs, subprocess.Popen.kill() is called, which uses SIGKILL. If the subprocess is a wrapper script, no cleanup can occur since SIGKILL cannot be handled. We should try SIGINT or SIGTERM first to give the child a chance to cleanup.

Concretely, if run with ffpuppet as a subprocess, this leaves orphaned Firefox (and Xvfb if --xvfb is used) processes on every timeout.

Also install pytest-catchlog via pip

Currently, when tests fail, I did not figure out how to see log messages unless pytest-catchlog got installed, at which point the logs become a lot more useful when I add my own logging calls (the WARNING logging message is the example):

================================== FAILURES ===================================
________________________ LithiumTests.test_arithmetic _________________________

self = <lithium.lithium.test_lithium.LithiumTests testMethod=test_arithmetic>

    def test_arithmetic(self):
        path = os.path.join(os.path.dirname(__file__), "examples", "arithmetic")
        log.warning(path)
        shutil.copyfile(os.path.join(path, "11.txt"), "11.txt")
        result = lithium.Lithium().main([os.path.join(path, "product_divides.py"), "35", "11.txt"])
        self.assertEqual(result, 0)
        with open("11.txt") as f:
            self.assertEqual(f.read(), "2\n\n# DDBEGIN\n5\n7\n# DDEND\n\n2\n")
        shutil.copyfile(os.path.join(path, "11.txt"), "11.txt")
        result = lithium.Lithium().main(["-c", os.path.join(path, "product_divides.py"), "35", "11.txt"])
        self.assertEqual(result, 0)
        with open("11.txt") as f:
>           self.assertEqual(f.read(), "2\n\n# DDBEGIN\n5\n7\n# DDEND\n\n2\n")
E           AssertionError: '2\n\n# DDBEGIN\n0\n# DDEND\n\n2\n' != '2\n\n# DDBEGIN\n5\n7\n# DDEND\n\n2\n'

lithium\test_lithium.py:305: AssertionError
---------------------------- Captured stdout call -----------------------------
159667200 is divisible by 35
3960 is not divisible by 35
161280 is divisible by 35
6720 is divisible by 35
4 is not divisible by 35
224 is not divisible by 35
120 is not divisible by 35
1344 is not divisible by 35
1120 is divisible by 35
160 is not divisible by 35
140 is divisible by 35
28 is not divisible by 35
20 is not divisible by 35
159667200 is divisible by 35
4 is not divisible by 35
14515200 is divisible by 35
20160 is divisible by 35
4 is not divisible by 35
360 is not divisible by 35
224 is not divisible by 35
2880 is not divisible by 35
40 is not divisible by 35
0 is divisible by 35
224 is not divisible by 35
0 is divisible by 35
0 is divisible by 35
0 is divisible by 35
0 is divisible by 35
4 is not divisible by 35
0 is divisible by 35
4 is not divisible by 35
0 is divisible by 35
4 is not divisible by 35
---------------------------- Captured stderr call -----------------------------
WARNING:lithium_test:c:\Users\skywinxps\lithium\lithium\examples\arithmetic
INFO:lithium:Intermediate files will be stored in tmp1\.
INFO:lithium:The original testcase has 11 lines.
INFO:lithium:Checking that the original testcase is 'interesting'...
INFO:lithium:Removing a chunk of size 8 starting at 0 of 11 made the file 'uninteresting'.
INFO:lithium:Removing a chunk of size 8 starting at 8 of 11 was a successful reduction :)
INFO:lithium:
INFO:lithium:Halving chunk size to 4
INFO:lithium:Removing a chunk of size 4 starting at 0 of 8 was a successful reduction :)
INFO:lithium:Removing a chunk of size 4 starting at 0 of 4 made the file 'uninteresting'.
INFO:lithium:
INFO:lithium:Halving chunk size to 2
INFO:lithium:Removing a chunk of size 2 starting at 0 of 4 made the file 'uninteresting'.
INFO:lithium:Removing a chunk of size 2 starting at 2 of 4 made the file 'uninteresting'.
INFO:lithium:
INFO:lithium:Halving chunk size to 1
INFO:lithium:Removing a chunk of size 1 starting at 0 of 4 made the file 'uninteresting'.
INFO:lithium:Removing a chunk of size 1 starting at 1 of 4 was a successful reduction :)
INFO:lithium:Removing a chunk of size 1 starting at 1 of 3 made the file 'uninteresting'.
INFO:lithium:Removing a chunk of size 1 starting at 2 of 3 was a successful reduction :)
INFO:lithium:
INFO:lithium:Starting another round of chunk size 1
INFO:lithium:Removing a chunk of size 1 starting at 0 of 2 made the file 'uninteresting'.
INFO:lithium:Removing a chunk of size 1 starting at 1 of 2 made the file 'uninteresting'.
INFO:lithium:
INFO:lithium:Lithium result: succeeded, reduced to: 2 lines
INFO:lithium:=== LITHIUM SUMMARY ===
INFO:lithium:  Removing any single line from the final file makes it uninteresting!
INFO:lithium:  Initial size: 11 lines
INFO:lithium:  Final size: 2 lines
INFO:lithium:  Tests performed: 13
INFO:lithium:  Test total: 42 lines
INFO:lithium:Intermediate files will be stored in tmp2\.
INFO:lithium:The original testcase has 34 chars.
INFO:lithium:Checking that the original testcase is 'interesting'...
INFO:lithium:Removing a chunk of size 32 starting at 0 of 34 made the file 'uninteresting'.
INFO:lithium:Removing a chunk of size 32 starting at 32 of 34 was a successful reduction :)
INFO:lithium:
INFO:lithium:Halving chunk size to 16
INFO:lithium:Removing a chunk of size 16 starting at 0 of 32 was a successful reduction :)
INFO:lithium:Removing a chunk of size 16 starting at 0 of 16 made the file 'uninteresting'.
INFO:lithium:
INFO:lithium:Halving chunk size to 8
INFO:lithium:Removing a chunk of size 8 starting at 0 of 16 made the file 'uninteresting'.
INFO:lithium:Removing a chunk of size 8 starting at 8 of 16 made the file 'uninteresting'.
INFO:lithium:
INFO:lithium:Halving chunk size to 4
INFO:lithium:Removing a chunk of size 4 starting at 0 of 16 made the file 'uninteresting'.
INFO:lithium:Removing a chunk of size 4 starting at 4 of 16 made the file 'uninteresting'.
INFO:lithium:Removing a chunk of size 4 starting at 8 of 16 was a successful reduction :)
INFO:lithium:Removing a chunk of size 4 starting at 8 of 12 made the file 'uninteresting'.
INFO:lithium:
INFO:lithium:Halving chunk size to 2
INFO:lithium:Removing a chunk of size 2 starting at 0 of 12 was a successful reduction :)
INFO:lithium:Removing a chunk of size 2 starting at 0 of 10 was a successful reduction :)
INFO:lithium:Removing a chunk of size 2 starting at 0 of 8 was a successful reduction :)
INFO:lithium:Removing a chunk of size 2 starting at 0 of 6 was a successful reduction :)
INFO:lithium:Removing a chunk of size 2 starting at 0 of 4 made the file 'uninteresting'.
INFO:lithium:Removing a chunk of size 2 starting at 2 of 4 was a successful reduction :)
INFO:lithium:
INFO:lithium:Halving chunk size to 1
INFO:lithium:Removing a chunk of size 1 starting at 0 of 2 made the file 'uninteresting'.
INFO:lithium:Removing a chunk of size 1 starting at 1 of 2 was a successful reduction :)
INFO:lithium:
INFO:lithium:Starting another round of chunk size 1
INFO:lithium:Removing a chunk of size 1 starting at 0 of 1 made the file 'uninteresting'.
INFO:lithium:
INFO:lithium:Lithium result: succeeded, reduced to: 1 char
INFO:lithium:=== LITHIUM SUMMARY ===
INFO:lithium:  Removing any single char from the final file makes it uninteresting!
INFO:lithium:  Initial size: 34 chars
INFO:lithium:  Final size: 1 char
INFO:lithium:  Tests performed: 20
INFO:lithium:  Test total: 178 chars
------------------------------ Captured log call ------------------------------
test_lithium.py            295 WARNING  c:\Users\skywinxps\lithium\lithium\examples\arithmetic
lithium.py                1118 INFO     Intermediate files will be stored in tmp1\.
lithium.py                 245 INFO     The original testcase has 11 lines.
lithium.py                 246 INFO     Checking that the original testcase is 'interesting'...
lithium.py                 325 INFO     Removing a chunk of size 8 starting at 0 of 11 made the file 'uninteresting'.
lithium.py                 321 INFO     Removing a chunk of size 8 starting at 8 of 11 was a successful reduction :)
lithium.py                 300 INFO
lithium.py                 311 INFO     Halving chunk size to 4
lithium.py                 321 INFO     Removing a chunk of size 4 starting at 0 of 8 was a successful reduction :)
lithium.py                 325 INFO     Removing a chunk of size 4 starting at 0 of 4 made the file 'uninteresting'.
lithium.py                 300 INFO
lithium.py                 311 INFO     Halving chunk size to 2
lithium.py                 325 INFO     Removing a chunk of size 2 starting at 0 of 4 made the file 'uninteresting'.
lithium.py                 325 INFO     Removing a chunk of size 2 starting at 2 of 4 made the file 'uninteresting'.
lithium.py                 300 INFO
lithium.py                 311 INFO     Halving chunk size to 1
lithium.py                 325 INFO     Removing a chunk of size 1 starting at 0 of 4 made the file 'uninteresting'.
lithium.py                 321 INFO     Removing a chunk of size 1 starting at 1 of 4 was a successful reduction :)
lithium.py                 325 INFO     Removing a chunk of size 1 starting at 1 of 3 made the file 'uninteresting'.
lithium.py                 321 INFO     Removing a chunk of size 1 starting at 2 of 3 was a successful reduction :)
lithium.py                 300 INFO
lithium.py                 304 INFO     Starting another round of chunk size 1
lithium.py                 325 INFO     Removing a chunk of size 1 starting at 0 of 2 made the file 'uninteresting'.
lithium.py                 325 INFO     Removing a chunk of size 1 starting at 1 of 2 made the file 'uninteresting'.
lithium.py                 300 INFO
lithium.py                 306 INFO     Lithium result: succeeded, reduced to: 2 lines
lithium.py                1294 INFO     === LITHIUM SUMMARY ===
lithium.py                 264 INFO       Removing any single line from the final file makes it uninteresting!
lithium.py                 266 INFO       Initial size: 11 lines
lithium.py                 267 INFO       Final size: 2 lines
lithium.py                1122 INFO       Tests performed: 13
lithium.py                1123 INFO       Test total: 42 lines
lithium.py                1118 INFO     Intermediate files will be stored in tmp2\.
lithium.py                 245 INFO     The original testcase has 34 chars.
lithium.py                 246 INFO     Checking that the original testcase is 'interesting'...
lithium.py                 325 INFO     Removing a chunk of size 32 starting at 0 of 34 made the file 'uninteresting'.
lithium.py                 321 INFO     Removing a chunk of size 32 starting at 32 of 34 was a successful reduction :)
lithium.py                 300 INFO
lithium.py                 311 INFO     Halving chunk size to 16
lithium.py                 321 INFO     Removing a chunk of size 16 starting at 0 of 32 was a successful reduction :)
lithium.py                 325 INFO     Removing a chunk of size 16 starting at 0 of 16 made the file 'uninteresting'.
lithium.py                 300 INFO
lithium.py                 311 INFO     Halving chunk size to 8
lithium.py                 325 INFO     Removing a chunk of size 8 starting at 0 of 16 made the file 'uninteresting'.
lithium.py                 325 INFO     Removing a chunk of size 8 starting at 8 of 16 made the file 'uninteresting'.
lithium.py                 300 INFO
lithium.py                 311 INFO     Halving chunk size to 4
lithium.py                 325 INFO     Removing a chunk of size 4 starting at 0 of 16 made the file 'uninteresting'.
lithium.py                 325 INFO     Removing a chunk of size 4 starting at 4 of 16 made the file 'uninteresting'.
lithium.py                 321 INFO     Removing a chunk of size 4 starting at 8 of 16 was a successful reduction :)
lithium.py                 325 INFO     Removing a chunk of size 4 starting at 8 of 12 made the file 'uninteresting'.
lithium.py                 300 INFO
lithium.py                 311 INFO     Halving chunk size to 2
lithium.py                 321 INFO     Removing a chunk of size 2 starting at 0 of 12 was a successful reduction :)
lithium.py                 321 INFO     Removing a chunk of size 2 starting at 0 of 10 was a successful reduction :)
lithium.py                 321 INFO     Removing a chunk of size 2 starting at 0 of 8 was a successful reduction :)
lithium.py                 321 INFO     Removing a chunk of size 2 starting at 0 of 6 was a successful reduction :)
lithium.py                 325 INFO     Removing a chunk of size 2 starting at 0 of 4 made the file 'uninteresting'.
lithium.py                 321 INFO     Removing a chunk of size 2 starting at 2 of 4 was a successful reduction :)
lithium.py                 300 INFO
lithium.py                 311 INFO     Halving chunk size to 1
lithium.py                 325 INFO     Removing a chunk of size 1 starting at 0 of 2 made the file 'uninteresting'.
lithium.py                 321 INFO     Removing a chunk of size 1 starting at 1 of 2 was a successful reduction :)
lithium.py                 300 INFO
lithium.py                 304 INFO     Starting another round of chunk size 1
lithium.py                 325 INFO     Removing a chunk of size 1 starting at 0 of 1 made the file 'uninteresting'.
lithium.py                 300 INFO
lithium.py                 306 INFO     Lithium result: succeeded, reduced to: 1 char
lithium.py                1294 INFO     === LITHIUM SUMMARY ===
lithium.py                 264 INFO       Removing any single char from the final file makes it uninteresting!
lithium.py                 266 INFO       Initial size: 34 chars
lithium.py                 267 INFO       Final size: 1 char
lithium.py                1122 INFO       Tests performed: 20
lithium.py                1123 INFO       Test total: 178 chars
===================== 1 failed, 16 passed in 1.63 seconds =====================

Coverage not running properly on AppVeyor for Python 2.7 64-bit and 3+

As far back as rev 820fb5c, Python 2.7 64-bit and 3+ coverage was not running properly on AppVeyor, but this still shows up as green.

%PYTHON%\python.exe -m codecov -X gcov
'coverage' is not recognized as an internal or external command,
operable program or batch file.
      _____          _
     / ____|        | |
    | |     ___   __| | ___  ___ _____   __
    | |    / _ \ / _  |/ _ \/ __/ _ \ \ / /
    | |___| (_) | (_| |  __/ (_| (_) \ V /
     \_____\___/ \____|\___|\___\___/ \_/
                                    v2.0.9
==> Detecting CI provider
    AppVeyor Detected
==> Preparing upload
XX> Skip processing gcov
==> Collecting reports
XX> Searching for reports disabled
    Generating coverage xml reports for Python
    Error running `coverage xml -i`: None
    - Ignored: [Errno 2] No such file or directory: 'C:\\projects\\lithium\\coverage.xml'
Error: No coverage report found
Tip: See all example repositories: https://github.com/codecov?query=example
Support channels:
  Email:   [email protected]
  IRC:     #codecov
  Gitter:  https://gitter.im/codecov/support
  Twitter: @codecov
Build success

pip installations are successful though, along with Python 2.7 32-bit:

%PYTHON%\python.exe -m codecov -X gcov
      _____          _
     / ____|        | |
    | |     ___   __| | ___  ___ _____   __
    | |    / _ \ / _  |/ _ \/ __/ _ \ \ / /
    | |___| (_) | (_| |  __/ (_| (_) \ V /
     \_____\___/ \____|\___|\___\___/ \_/
                                    v2.0.9
==> Detecting CI provider
    AppVeyor Detected
==> Preparing upload
XX> Skip processing gcov
==> Collecting reports
XX> Searching for reports disabled
    Generating coverage xml reports for Python
    + C:\projects\lithium\coverage.xml bytes=59330
==> Uploading
    .url https://codecov.io
    .query service=appveyor&package=py2.0.9&job=MozillaSecurity%2Flithium%2F1.0.195&build=m4jmegnilm9nxowo&branch=master&commit=820fb5cca91d5f8b137722e361f291ffdf8e0d1f&slug=MozillaSecurity%2Flithium
    Pinging Codecov...
    Uploading to S3...
    https://codecov.io/github/MozillaSecurity/lithium/commit/820fb5cca91d5f8b137722e361f291ffdf8e0d1f
Build success

Coverage runs properly on all systems and versions on Travis. @jschwartzentruber, were you aware of this?

Skip testing with empty testcase when large chunks are removed

Currently if we have a testcase of size 4246 and our first reduction pass of size 4096 is successful we then have a testcase of size 150. Then we will try to remove the remaining part and then reduce the chunk size by 1/2. The problem here is we will then try with 2048, 1024, 512, 256, before getting to 128. This means we will test with an empty testcase 5 times. This can be optimized. PR to come.

Here is an example log of the issue:

Intermediate files will be stored in tmp129/.
The original testcase has 4246 lines.
Checking that the original testcase is 'interesting'...
Interesting: Assertion failure: blah... blah... blah...
Updating poll timeout to: 10
Updating max timeout to: 10
Interesting: Assertion failure: blah... blah... blah...
Removing a chunk of size 4096 starting at 0 of 4246 was a successful reduction :)
Uninteresting: no failure detected
Removing a chunk of size 4096 starting at 0 of 150 made the file 'uninteresting'.

Halving chunk size to 2048
Uninteresting: no failure detected
Removing a chunk of size 2048 starting at 0 of 150 made the file 'uninteresting'.

Halving chunk size to 1024
Uninteresting: no failure detected
Removing a chunk of size 1024 starting at 0 of 150 made the file 'uninteresting'.

Halving chunk size to 512
Uninteresting: no failure detected
Removing a chunk of size 512 starting at 0 of 150 made the file 'uninteresting'.

Halving chunk size to 256
Uninteresting: no failure detected
Removing a chunk of size 256 starting at 0 of 150 made the file 'uninteresting'.

Halving chunk size to 128
Uninteresting: no failure detected
Removing a chunk of size 128 starting at 0 of 150 made the file 'uninteresting'.
Interesting: Assertion failure: blah... blah... blah...
Removing a chunk of size 128 starting at 128 of 150 was a successful reduction :)

CODE_OF_CONDUCT.md file missing

As of January 1 2019, Mozilla requires that all GitHub projects include this CODE_OF_CONDUCT.md file in the project root. The file has two parts:

  1. Required Text - All text under the headings Community Participation Guidelines and How to Report, are required, and should not be altered.
  2. Optional Text - The Project Specific Etiquette heading provides a space to speak more specifically about ways people can work effectively and inclusively together. Some examples of those can be found on the Firefox Debugger project, and Common Voice. (The optional part is commented out in the raw template file, and will not be visible until you modify and uncomment that part.)

If you have any questions about this file, or Code of Conduct policies and procedures, please see Mozilla-GitHub-Standards or email [email protected].

(Message COC001)

Lithium should not try reductions which have already been tested.

If we have a testcase containing abc, and bc is the reduced result (--char mode, strategy=minimize), the run will look like this:

bc ➡️ interesting
c ➡️ not interesting
b ➡️ not interesting
Starting another round with chunk size 1
c ➡️ not interesting
b ➡️ not interesting

This final round of chunk size 1 will always be unneeded as long as the reduction in the previous round was only at the beginning. I think this will be true for all atom types (line/char/symbol) and strategies.

Move away from py.test in Travis .yml config

We are using py.test in .travis.yml but not in .appveyor.yml - I thought it was the same as pytest or python -m pytest but apparently they are all different.

References:

So it seems like we should at least move away from py.test. @jschwartzentruber what do you think it should be, pytest or python -m pytest?

Lithium should be installable

Lithium should define a setup.py and be laid out such that it can be used as a library or an executable. This makes distribution easier and allows the standard import system to be used if using it as a library (possible after #14).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.