reorganize the code and add test cases