do some refactoring
add some test cases