add lots of tests, fix some bugs