import bisect
import random
import unittest
from example import lower_bound, minimum_capacity


class BinaryTests(unittest.TestCase):
    def test_boundaries(self):
        for values in ([], [2], [1, 3, 3, 6], [4] * 6):
            for target in range(-1, 9):
                self.assertEqual(lower_bound(values, target), bisect.bisect_left(values, target))

    def test_capacity(self):
        self.assertEqual(minimum_capacity([3, 2, 2, 4], 2), 6)
        self.assertEqual(minimum_capacity([], 2), 0)
        with self.assertRaises(ValueError):
            minimum_capacity([0], 1)

    def test_capacity_against_enumeration(self):
        rng = random.Random(8)
        for _ in range(60):
            weights = [rng.randint(1, 8) for _ in range(rng.randint(1, 8))]
            days = rng.randint(1, 8)
            def needed(cap):
                used, load = 1, 0
                for w in weights:
                    if load + w > cap:
                        used += 1
                        load = 0
                    load += w
                return used
            expected = next(c for c in range(max(weights), sum(weights) + 1)
                            if needed(c) <= days)
            self.assertEqual(minimum_capacity(weights, days), expected)


if __name__ == '__main__':
    unittest.main()
