Switch to callbacks, add tests