final version with testcases