66 lines
2.9 KiB
Python
66 lines
2.9 KiB
Python
"""Cross-port contract: Python/ctypes and Kotlin/JNI consume the same fixtures."""
|
|
import ctypes
|
|
import json
|
|
import math
|
|
import os
|
|
from pathlib import Path
|
|
import unittest
|
|
from dataclasses import replace
|
|
|
|
from protocan.plot import Bounds, Marker, Markers, PlotMath, Viewport
|
|
|
|
|
|
@unittest.skipUnless(os.environ.get("SETPROTOCOL_LIBRARY"), "Set SETPROTOCOL_LIBRARY to the built C library")
|
|
class PlotTests(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.core = PlotMath(ctypes.CDLL(os.environ["SETPROTOCOL_LIBRARY"]))
|
|
|
|
def test_shared_numeric_fixtures(self):
|
|
path = Path(__file__).resolve().parents[2] / "c/set-protocol/tests/fixtures/plot-v1.json"
|
|
for case in json.loads(path.read_text())["cases"]:
|
|
with self.subTest(case=case["name"]):
|
|
if case["output"] is None:
|
|
with self.assertRaises(ValueError):
|
|
self.core.call(case["op"], *case["input"])
|
|
else:
|
|
actual = self.core.call(case["op"], *case["input"])
|
|
self.assertEqual(len(actual), len(case["output"]))
|
|
for a, b in zip(actual, case["output"]):
|
|
self.assertAlmostEqual(a, b, places=10)
|
|
|
|
def test_markers_stay_in_data_coordinates_and_cross(self):
|
|
bounds = Bounds(1000, 2000, -10, 10)
|
|
markers = Markers().positioned(self.core, bounds)
|
|
self.assertTrue(markers.enabled(Marker.A))
|
|
self.assertFalse(markers.enabled(Marker.C))
|
|
self.assertTrue(replace(markers, x_pairs=2).enabled(Marker.C))
|
|
zoomed = bounds.visible(self.core, Viewport(.25, .25, .5, .5))
|
|
self.assertEqual(markers, markers.positioned(self.core, zoomed))
|
|
moved = markers.drag(self.core, Marker.A, 50, 500, zoomed)
|
|
self.assertAlmostEqual(moved.a, markers.a + 50)
|
|
self.assertEqual(markers.b, moved.b)
|
|
self.assertEqual(Marker.A, moved.hit(self.core, 0, 50, 500, 100, 20, zoomed))
|
|
crossed = markers.move(Marker.A, 1900).move(Marker.B, 1100)
|
|
self.assertEqual(-800, self.core.delta(crossed.a, crossed.b))
|
|
|
|
def test_invalid_numeric_inputs_do_not_escape_to_painter(self):
|
|
for value in (math.nan, math.inf, -math.inf):
|
|
self.assertEqual(Viewport(), Viewport().transform(self.core, zoom_x=value))
|
|
with self.assertRaises(ValueError):
|
|
self.core.pinch_axis(value, 10, 8)
|
|
|
|
def test_locked_viewport_and_decibel_delta(self):
|
|
locked = Viewport(locked=True)
|
|
self.assertEqual(locked, locked.transform(self.core, zoom_x=2, pan_y=.2))
|
|
self.assertAlmostEqual(20, self.core.db_delta(1, 10))
|
|
self.assertAlmostEqual(-20, self.core.db_delta(10, 1))
|
|
self.assertIsNone(self.core.db_delta(0, 1))
|
|
self.assertEqual(Bounds(0, 500, -2, 2), self.core.limits(0, 500, -2, 2))
|
|
with self.assertRaises(ValueError):
|
|
self.core.limits(1, 1, -2, 2)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|