solution with tests