import importlib.util
import random
import sys
import unittest
from pathlib import Path
spec = importlib.util.spec_from_file_location(
"candidate", Path(sys.argv.pop(1)) / "interval_set.py"
)
assert spec is not None and spec.loader is not None
m = importlib.util.module_from_spec(spec)
spec.loader.exec_module(m)
def points(intervals):
return {x for a, b in intervals for x in range(a, b)}
def canonical(values):
out = []
for value in sorted(values):
if out and out[-1][1] == value:
out[-1] = (out[-1][0], value + 1)
else:
out.append((value, value + 1))
return out
class IndependentTests(unittest.TestCase):
def test_boundaries(self):
self.assertEqual(
m.normalize([(5, 5), (2, 4), (0, 2), (1, 3), (0, 2)]), [(0, 4)]
)
self.assertEqual(m.intersection([(0, 2)], [(2, 4)]), [])
self.assertEqual(
m.difference([(0, 10)], [(2, 4), (6, 8)]), [(0, 2), (4, 6), (8, 10)]
)
self.assertEqual(m.difference([(0, 10)], [(-1, 11)]), [])
self.assertEqual(m.union([], []), [])
def test_huge_endpoints(self):
h = 10**100
self.assertEqual(m.union([(-h, 0)], [(0, h)]), [(-h, h)])
self.assertEqual(m.difference([(-h, h)], [(-1, 1)]), [(-h, -1), (1, h)])
self.assertEqual(m.intersection([(-h, h)], [(h - 1, h + 1)]), [(h - 1, h)])
def test_reversed_rejected(self):
with self.assertRaises(ValueError):
m.normalize([(2, 1)])
for fn in (m.union, m.intersection, m.difference):
with self.assertRaises(ValueError):
fn([], [(2, 1)])
with self.assertRaises(ValueError):
fn([(2, 1)], [])
def test_inputs_not_mutated(self):
a = [(3, 5), (0, 2), (1, 4)]
b = [(2, 3), (7, 8)]
for fn in (m.union, m.intersection, m.difference):
fn(a, b)
self.assertEqual(a, [(3, 5), (0, 2), (1, 4)])
self.assertEqual(b, [(2, 3), (7, 8)])
m.normalize(a)
self.assertEqual(a, [(3, 5), (0, 2), (1, 4)])
def test_2000_random_pairs_and_generators(self):
rng = random.Random(947120)
for _ in range(2000):
a = [
tuple(sorted((rng.randrange(-20, 21), rng.randrange(-20, 21))))
for _ in range(rng.randrange(15))
]
b = [
tuple(sorted((rng.randrange(-20, 21), rng.randrange(-20, 21))))
for _ in range(rng.randrange(15))
]
pa, pb = points(a), points(b)
self.assertEqual(m.normalize(iter(a)), canonical(pa))
for fn, expected in [
(m.union, pa | pb),
(m.intersection, pa & pb),
(m.difference, pa - pb),
]:
self.assertEqual(fn(iter(a), iter(b)), canonical(expected))
unittest.main(verbosity=2)