refactor and add some more test