add test and a few improvement