add tests, some refactoring