Run test cases
diff --git a/.github/workflows/compile_test.yml b/.github/workflows/compile_test.yml
index 1960db2..59ddc6b 100644
--- a/.github/workflows/compile_test.yml
+++ b/.github/workflows/compile_test.yml
@@ -14,6 +14,11 @@
steps:
- uses: actions/checkout@v1
+ - name: Update submodules
+ run: |
+ git submodule init
+ git submodule update
+
- name: Setup python
uses: actions/setup-python@v1
with:
@@ -25,3 +30,6 @@
- name: Compile project
run: make
+
+ - name: Run tests
+ run: python run-tests.py
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..0174b67
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "third-party/json5-tests"]
+ path = third-party/json5-tests
+ url = https://github.com/json5/json5-tests.git
diff --git a/requirements.txt b/requirements.txt
index c5ef52b..c963038 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,4 @@
+colorama == 0.*, >= 0.4.3
cython == 0.*, >= 0.29.14
more_itertools == 8.*, >= 8.0.2
sphinx == 2.*, >= 2.2.2
diff --git a/run-tests.py b/run-tests.py
new file mode 100755
index 0000000..32cf988
--- /dev/null
+++ b/run-tests.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+
+from argparse import ArgumentParser
+from logging import basicConfig, INFO, getLogger
+from pathlib import Path
+from subprocess import Popen
+
+from colorama import init, Fore
+from pyjson5 import decode_io
+
+
+argparser = ArgumentParser(description='Run JSON5 parser tests')
+argparser.add_argument('tests', nargs='?', type=Path, default=Path('third-party/json5-tests'))
+
+suffix_implies_success = {
+ '.json': True,
+ '.json5': True,
+ '.txt': False,
+}
+
+if __name__ == '__main__':
+ basicConfig(level=INFO)
+ logger = getLogger(__name__)
+
+ init()
+
+ good = 0
+ bad = 0
+ severe = 0
+
+ args = argparser.parse_args()
+ index = 0
+ for path in sorted(args.tests.glob('*/*.*')):
+ kind = path.suffix.split('.')[-1]
+ expect_success = suffix_implies_success.get(path.suffix)
+ if expect_success is None:
+ continue
+
+ index += 1
+ category = path.parent.name
+ name = path.stem
+ try:
+ p = Popen(('/usr/bin/env', 'python', 'transcode-to-json.py', str(path)))
+ outcome = p.wait(5)
+ except Exception:
+ logger.error('Error while testing: %s', path, exc_info=True)
+ errors += 1
+ continue
+
+ is_success = outcome == 0
+ is_failure = outcome == 1
+ is_severe = outcome not in (0, 1)
+ is_good = is_success if expect_success else is_failure
+
+ code = (
+ Fore.RED + '๐ฑ' if is_severe else
+ Fore.CYAN + '๐' if is_good else
+ Fore.YELLOW + '๐ '
+ )
+ print(
+ '#', index, ' ', code, ' '
+ 'Category <', category, '> | '
+ 'Test <', name, '> | '
+ 'Data <', kind, '> | '
+ 'Expected <', 'pass' if expect_success else 'FAIL', '> | '
+ 'Actual <', 'pass' if is_success else 'FAIL', '>',
+ Fore.RESET,
+ sep='',
+ )
+ if is_severe:
+ severe += 1
+ elif is_good:
+ good += 1
+ else:
+ bad += 1
+
+ is_severe = severe > 0
+ is_good = bad == 0
+ code = (
+ Fore.RED + '๐ฑ' if is_severe else
+ Fore.CYAN + '๐' if is_good else
+ Fore.YELLOW + '๐ '
+ )
+ print()
+ print(
+ code, ' ',
+ good, ' × correct outcome | ',
+ bad, ' × wrong outcome | ',
+ severe, ' × severe errors',
+ Fore.RESET,
+ sep=''
+ )
+ raise SystemExit(2 if is_severe else 0 if is_good else 1)
diff --git a/third-party/json5-tests b/third-party/json5-tests
new file mode 160000
index 0000000..c9af328
--- /dev/null
+++ b/third-party/json5-tests
@@ -0,0 +1 @@
+Subproject commit c9af328e6d77286d78b77b520c4622d588b544c0
diff --git a/transcode-to-json.py b/transcode-to-json.py
new file mode 100755
index 0000000..bb674b4
--- /dev/null
+++ b/transcode-to-json.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+from argparse import ArgumentParser
+from logging import basicConfig, DEBUG, getLogger
+from pathlib import Path
+
+from pyjson5 import decode, encode
+
+
+argparser = ArgumentParser(description='Run JSON5 parser tests')
+argparser.add_argument('input', type=Path)
+argparser.add_argument('output', nargs='?', type=Path)
+
+if __name__ == '__main__':
+ basicConfig(level=DEBUG)
+ logger = getLogger(__name__)
+
+ args = argparser.parse_args()
+ try:
+ # open() does not work with Paths in Python 3.5
+ with open(str(args.input.resolve()), 'rt') as f:
+ data = f.read()
+ except Exception:
+ logger.error('Could not even read file: %s', args.input, exc_info=True)
+ raise SystemExit(-1)
+
+ try:
+ obj = decode(data)
+ except Exception:
+ logger.error('Could not parse content: %s', args.input)
+ raise SystemExit(1)
+
+ try:
+ data = encode(obj)
+ except Exception:
+ logger.error('Could open stringify content: %s', args.input, exc_info=True)
+ raise SystemExit(2)
+
+ if args.output is not None:
+ try:
+ # open() does not work with Paths in Python 3.5
+ with open(str(args.output.resolve()), 'wt') as f:
+ f.write(data)
+ except Exception:
+ logger.error('Could open output file: %s', args.output, exc_info=True)
+ raise SystemExit(-1)
+
+ raise SystemExit(0)
+