add unit tests, some refactoring