Add "JSON is a Minefield" tests
diff --git a/.github/workflows/compile_test.yml b/.github/workflows/compile_test.yml
index 59ddc6b..f5ddec1 100644
--- a/.github/workflows/compile_test.yml
+++ b/.github/workflows/compile_test.yml
@@ -31,5 +31,8 @@
- name: Compile project
run: make
- - name: Run tests
+ - name: Run JSON5 tests suite
run: python run-tests.py
+
+ - name: Run "JSON is a Minefield" suite
+ run: python run-minefield-test.py
diff --git a/.gitmodules b/.gitmodules
index 0174b67..158669b 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
[submodule "third-party/json5-tests"]
path = third-party/json5-tests
url = https://github.com/json5/json5-tests.git
+[submodule "third-party/JSONTestSuite"]
+ path = third-party/JSONTestSuite
+ url = https://github.com/nst/JSONTestSuite.git
diff --git a/run-minefield-test.py b/run-minefield-test.py
new file mode 100755
index 0000000..23a34d2
--- /dev/null
+++ b/run-minefield-test.py
@@ -0,0 +1,94 @@
+#!/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/JSONTestSuite/test_parsing'))
+
+suffix_implies_success = {
+ 'json': True,
+ 'json5': True,
+ 'txt': False,
+}
+
+if __name__ == '__main__':
+ basicConfig(level=INFO)
+ logger = getLogger(__name__)
+
+ init()
+
+ good = bad = severe = 0
+
+ args = argparser.parse_args()
+ index = 0
+ for path in sorted(args.tests.glob('?_?*.json')):
+ category, name = path.stem.split('_', 1)
+ if category not in 'yni':
+ continue
+
+ if category in 'ni':
+ # ignore anything but tests that are expected to pass for now
+ continue
+
+ try:
+ # ignore any UTF-8 errors
+ with open(str(path.resolve()), 'rt') as f:
+ f.read()
+ except Exception:
+ continue
+
+ index += 1
+ 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
+
+ if outcome not in (0, 1):
+ code = Fore.RED + 'π±'
+ severe += 1
+ elif category == 'y':
+ if outcome == 0:
+ code = Fore.CYAN + 'π'
+ good += 1
+ else:
+ code = Fore.YELLOW + 'π '
+ bad += 1
+ else:
+ code = Fore.BLUE + 'π
'
+
+ print(
+ '#', index, ' ', code, ' '
+ 'Category <', category, '> | '
+ 'Test <', name, '> | '
+ 'Actual <', 'pass' if outcome == 0 else 'FAIL', '>',
+ Fore.RESET,
+ sep='',
+ )
+
+ 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/JSONTestSuite b/third-party/JSONTestSuite
new file mode 160000
index 0000000..9f23c68
--- /dev/null
+++ b/third-party/JSONTestSuite
@@ -0,0 +1 @@
+Subproject commit 9f23c68b521dd700e8c99151d6dc1c5c52a0246e