Files
templates/python/tests/test_plot.py

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()