import unittest
from example import plan_tasks


class PlannerTests(unittest.TestCase):
    def test_parallel_dependencies(self):
        durations = {'fetch': 2, 'parse': 3, 'image': 4, 'publish': 1}
        dependencies = {'parse': ['fetch'], 'image': ['fetch'], 'publish': ['parse', 'image']}
        result = plan_tasks(durations, dependencies)
        self.assertEqual(result['total'], 7)
        self.assertEqual(result['start']['publish'], 6)
        self.assertEqual(set(result['order']), set(durations))
        for child, parents in dependencies.items():
            for parent in parents:
                self.assertLessEqual(result['finish'][parent], result['start'][child])

    def test_empty_zero_duplicate(self):
        self.assertEqual(plan_tasks({}, {})['total'], 0)
        result = plan_tasks({'a': 0, 'b': 2}, {'b': ['a', 'a']})
        self.assertEqual(result['total'], 2)
        self.assertEqual(result['order'], ['a', 'b'])

    def test_cycles_and_bad_input(self):
        for durations, dependencies in [({'a': 1}, {'a': ['a']}),
                                        ({'a': 1, 'b': 1, 'c': 1}, {'a': ['b'], 'b': ['a'], 'c': ['b']}),
                                        ({'a': 1}, {'a': ['missing']}),
                                        ({'a': -1}, {})]:
            with self.assertRaises(ValueError):
                plan_tasks(durations, dependencies)


if __name__ == '__main__':
    unittest.main()
