add test, some code refactor