graphdb_test.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. package graphdb
  2. import (
  3. "database/sql"
  4. "fmt"
  5. "os"
  6. "path"
  7. "strconv"
  8. "testing"
  9. _ "code.google.com/p/gosqlite/sqlite3"
  10. )
  11. func newTestDb(t *testing.T) (*Database, string) {
  12. p := path.Join(os.TempDir(), "sqlite.db")
  13. conn, err := sql.Open("sqlite3", p)
  14. db, err := NewDatabase(conn, true)
  15. if err != nil {
  16. t.Fatal(err)
  17. }
  18. return db, p
  19. }
  20. func destroyTestDb(dbPath string) {
  21. os.Remove(dbPath)
  22. }
  23. func TestNewDatabase(t *testing.T) {
  24. db, dbpath := newTestDb(t)
  25. if db == nil {
  26. t.Fatal("Database should not be nil")
  27. }
  28. db.Close()
  29. defer destroyTestDb(dbpath)
  30. }
  31. func TestCreateRootEnity(t *testing.T) {
  32. db, dbpath := newTestDb(t)
  33. defer destroyTestDb(dbpath)
  34. root := db.RootEntity()
  35. if root == nil {
  36. t.Fatal("Root entity should not be nil")
  37. }
  38. }
  39. func TestGetRootEntity(t *testing.T) {
  40. db, dbpath := newTestDb(t)
  41. defer destroyTestDb(dbpath)
  42. e := db.Get("/")
  43. if e == nil {
  44. t.Fatal("Entity should not be nil")
  45. }
  46. if e.ID() != "0" {
  47. t.Fatalf("Enity id should be 0, got %s", e.ID())
  48. }
  49. }
  50. func TestSetEntityWithDifferentName(t *testing.T) {
  51. db, dbpath := newTestDb(t)
  52. defer destroyTestDb(dbpath)
  53. db.Set("/test", "1")
  54. if _, err := db.Set("/other", "1"); err != nil {
  55. t.Fatal(err)
  56. }
  57. }
  58. func TestSetDuplicateEntity(t *testing.T) {
  59. db, dbpath := newTestDb(t)
  60. defer destroyTestDb(dbpath)
  61. if _, err := db.Set("/foo", "42"); err != nil {
  62. t.Fatal(err)
  63. }
  64. if _, err := db.Set("/foo", "43"); err == nil {
  65. t.Fatalf("Creating an entry with a duplciate path did not cause an error")
  66. }
  67. }
  68. func TestCreateChild(t *testing.T) {
  69. db, dbpath := newTestDb(t)
  70. defer destroyTestDb(dbpath)
  71. child, err := db.Set("/db", "1")
  72. if err != nil {
  73. t.Fatal(err)
  74. }
  75. if child == nil {
  76. t.Fatal("Child should not be nil")
  77. }
  78. if child.ID() != "1" {
  79. t.Fail()
  80. }
  81. }
  82. func TestListAllRootChildren(t *testing.T) {
  83. db, dbpath := newTestDb(t)
  84. defer destroyTestDb(dbpath)
  85. for i := 1; i < 6; i++ {
  86. a := strconv.Itoa(i)
  87. if _, err := db.Set("/"+a, a); err != nil {
  88. t.Fatal(err)
  89. }
  90. }
  91. entries := db.List("/", -1)
  92. if len(entries) != 5 {
  93. t.Fatalf("Expect 5 entries for / got %d", len(entries))
  94. }
  95. }
  96. func TestListAllSubChildren(t *testing.T) {
  97. db, dbpath := newTestDb(t)
  98. defer destroyTestDb(dbpath)
  99. _, err := db.Set("/webapp", "1")
  100. if err != nil {
  101. t.Fatal(err)
  102. }
  103. child2, err := db.Set("/db", "2")
  104. if err != nil {
  105. t.Fatal(err)
  106. }
  107. child4, err := db.Set("/logs", "4")
  108. if err != nil {
  109. t.Fatal(err)
  110. }
  111. if _, err := db.Set("/db/logs", child4.ID()); err != nil {
  112. t.Fatal(err)
  113. }
  114. child3, err := db.Set("/sentry", "3")
  115. if err != nil {
  116. t.Fatal(err)
  117. }
  118. if _, err := db.Set("/webapp/sentry", child3.ID()); err != nil {
  119. t.Fatal(err)
  120. }
  121. if _, err := db.Set("/webapp/db", child2.ID()); err != nil {
  122. t.Fatal(err)
  123. }
  124. entries := db.List("/webapp", 1)
  125. if len(entries) != 3 {
  126. t.Fatalf("Expect 3 entries for / got %d", len(entries))
  127. }
  128. entries = db.List("/webapp", 0)
  129. if len(entries) != 2 {
  130. t.Fatalf("Expect 2 entries for / got %d", len(entries))
  131. }
  132. }
  133. func TestAddSelfAsChild(t *testing.T) {
  134. db, dbpath := newTestDb(t)
  135. defer destroyTestDb(dbpath)
  136. child, err := db.Set("/test", "1")
  137. if err != nil {
  138. t.Fatal(err)
  139. }
  140. if _, err := db.Set("/test/other", child.ID()); err == nil {
  141. t.Fatal("Error should not be nil")
  142. }
  143. }
  144. func TestAddChildToNonExistantRoot(t *testing.T) {
  145. db, dbpath := newTestDb(t)
  146. defer destroyTestDb(dbpath)
  147. if _, err := db.Set("/myapp", "1"); err != nil {
  148. t.Fatal(err)
  149. }
  150. if _, err := db.Set("/myapp/proxy/db", "2"); err == nil {
  151. t.Fatal("Error should not be nil")
  152. }
  153. }
  154. func TestWalkAll(t *testing.T) {
  155. db, dbpath := newTestDb(t)
  156. defer destroyTestDb(dbpath)
  157. _, err := db.Set("/webapp", "1")
  158. if err != nil {
  159. t.Fatal(err)
  160. }
  161. child2, err := db.Set("/db", "2")
  162. if err != nil {
  163. t.Fatal(err)
  164. }
  165. child4, err := db.Set("/db/logs", "4")
  166. if err != nil {
  167. t.Fatal(err)
  168. }
  169. if _, err := db.Set("/webapp/logs", child4.ID()); err != nil {
  170. t.Fatal(err)
  171. }
  172. child3, err := db.Set("/sentry", "3")
  173. if err != nil {
  174. t.Fatal(err)
  175. }
  176. if _, err := db.Set("/webapp/sentry", child3.ID()); err != nil {
  177. t.Fatal(err)
  178. }
  179. if _, err := db.Set("/webapp/db", child2.ID()); err != nil {
  180. t.Fatal(err)
  181. }
  182. child5, err := db.Set("/gograph", "5")
  183. if err != nil {
  184. t.Fatal(err)
  185. }
  186. if _, err := db.Set("/webapp/same-ref-diff-name", child5.ID()); err != nil {
  187. t.Fatal(err)
  188. }
  189. if err := db.Walk("/", func(p string, e *Entity) error {
  190. t.Logf("Path: %s Entity: %s", p, e.ID())
  191. return nil
  192. }, -1); err != nil {
  193. t.Fatal(err)
  194. }
  195. }
  196. func TestGetEntityByPath(t *testing.T) {
  197. db, dbpath := newTestDb(t)
  198. defer destroyTestDb(dbpath)
  199. _, err := db.Set("/webapp", "1")
  200. if err != nil {
  201. t.Fatal(err)
  202. }
  203. child2, err := db.Set("/db", "2")
  204. if err != nil {
  205. t.Fatal(err)
  206. }
  207. child4, err := db.Set("/logs", "4")
  208. if err != nil {
  209. t.Fatal(err)
  210. }
  211. if _, err := db.Set("/db/logs", child4.ID()); err != nil {
  212. t.Fatal(err)
  213. }
  214. child3, err := db.Set("/sentry", "3")
  215. if err != nil {
  216. t.Fatal(err)
  217. }
  218. if _, err := db.Set("/webapp/sentry", child3.ID()); err != nil {
  219. t.Fatal(err)
  220. }
  221. if _, err := db.Set("/webapp/db", child2.ID()); err != nil {
  222. t.Fatal(err)
  223. }
  224. child5, err := db.Set("/gograph", "5")
  225. if err != nil {
  226. t.Fatal(err)
  227. }
  228. if _, err := db.Set("/webapp/same-ref-diff-name", child5.ID()); err != nil {
  229. t.Fatal(err)
  230. }
  231. entity := db.Get("/webapp/db/logs")
  232. if entity == nil {
  233. t.Fatal("Entity should not be nil")
  234. }
  235. if entity.ID() != "4" {
  236. t.Fatalf("Expected to get entity with id 4, got %s", entity.ID())
  237. }
  238. }
  239. func TestEnitiesPaths(t *testing.T) {
  240. db, dbpath := newTestDb(t)
  241. defer destroyTestDb(dbpath)
  242. _, err := db.Set("/webapp", "1")
  243. if err != nil {
  244. t.Fatal(err)
  245. }
  246. child2, err := db.Set("/db", "2")
  247. if err != nil {
  248. t.Fatal(err)
  249. }
  250. child4, err := db.Set("/logs", "4")
  251. if err != nil {
  252. t.Fatal(err)
  253. }
  254. if _, err := db.Set("/db/logs", child4.ID()); err != nil {
  255. t.Fatal(err)
  256. }
  257. child3, err := db.Set("/sentry", "3")
  258. if err != nil {
  259. t.Fatal(err)
  260. }
  261. if _, err := db.Set("/webapp/sentry", child3.ID()); err != nil {
  262. t.Fatal(err)
  263. }
  264. if _, err := db.Set("/webapp/db", child2.ID()); err != nil {
  265. t.Fatal(err)
  266. }
  267. child5, err := db.Set("/gograph", "5")
  268. if err != nil {
  269. t.Fatal(err)
  270. }
  271. if _, err := db.Set("/webapp/same-ref-diff-name", child5.ID()); err != nil {
  272. t.Fatal(err)
  273. }
  274. out := db.List("/", -1)
  275. for _, p := range out.Paths() {
  276. t.Log(p)
  277. }
  278. }
  279. func TestDeleteRootEntity(t *testing.T) {
  280. db, dbpath := newTestDb(t)
  281. defer destroyTestDb(dbpath)
  282. if err := db.Delete("/"); err == nil {
  283. t.Fatal("Error should not be nil")
  284. }
  285. }
  286. func TestDeleteEntity(t *testing.T) {
  287. db, dbpath := newTestDb(t)
  288. defer destroyTestDb(dbpath)
  289. _, err := db.Set("/webapp", "1")
  290. if err != nil {
  291. t.Fatal(err)
  292. }
  293. child2, err := db.Set("/db", "2")
  294. if err != nil {
  295. t.Fatal(err)
  296. }
  297. child4, err := db.Set("/logs", "4")
  298. if err != nil {
  299. t.Fatal(err)
  300. }
  301. if _, err := db.Set("/db/logs", child4.ID()); err != nil {
  302. t.Fatal(err)
  303. }
  304. child3, err := db.Set("/sentry", "3")
  305. if err != nil {
  306. t.Fatal(err)
  307. }
  308. if _, err := db.Set("/webapp/sentry", child3.ID()); err != nil {
  309. t.Fatal(err)
  310. }
  311. if _, err := db.Set("/webapp/db", child2.ID()); err != nil {
  312. t.Fatal(err)
  313. }
  314. child5, err := db.Set("/gograph", "5")
  315. if err != nil {
  316. t.Fatal(err)
  317. }
  318. if _, err := db.Set("/webapp/same-ref-diff-name", child5.ID()); err != nil {
  319. t.Fatal(err)
  320. }
  321. if err := db.Delete("/webapp/sentry"); err != nil {
  322. t.Fatal(err)
  323. }
  324. entity := db.Get("/webapp/sentry")
  325. if entity != nil {
  326. t.Fatal("Entity /webapp/sentry should be nil")
  327. }
  328. }
  329. func TestCountRefs(t *testing.T) {
  330. db, dbpath := newTestDb(t)
  331. defer destroyTestDb(dbpath)
  332. db.Set("/webapp", "1")
  333. if db.Refs("1") != 1 {
  334. t.Fatal("Expect reference count to be 1")
  335. }
  336. db.Set("/db", "2")
  337. db.Set("/webapp/db", "2")
  338. if db.Refs("2") != 2 {
  339. t.Fatal("Expect reference count to be 2")
  340. }
  341. }
  342. func TestPurgeId(t *testing.T) {
  343. db, dbpath := newTestDb(t)
  344. defer destroyTestDb(dbpath)
  345. db.Set("/webapp", "1")
  346. if db.Refs("1") != 1 {
  347. t.Fatal("Expect reference count to be 1")
  348. }
  349. db.Set("/db", "2")
  350. db.Set("/webapp/db", "2")
  351. count, err := db.Purge("2")
  352. if err != nil {
  353. t.Fatal(err)
  354. }
  355. if count != 2 {
  356. t.Fatal("Expected 2 references to be removed")
  357. }
  358. }
  359. func TestRename(t *testing.T) {
  360. db, dbpath := newTestDb(t)
  361. defer destroyTestDb(dbpath)
  362. db.Set("/webapp", "1")
  363. if db.Refs("1") != 1 {
  364. t.Fatal("Expect reference count to be 1")
  365. }
  366. db.Set("/db", "2")
  367. db.Set("/webapp/db", "2")
  368. if db.Get("/webapp/db") == nil {
  369. t.Fatal("Cannot find entity at path /webapp/db")
  370. }
  371. if err := db.Rename("/webapp/db", "/webapp/newdb"); err != nil {
  372. t.Fatal(err)
  373. }
  374. if db.Get("/webapp/db") != nil {
  375. t.Fatal("Entity should not exist at /webapp/db")
  376. }
  377. if db.Get("/webapp/newdb") == nil {
  378. t.Fatal("Cannot find entity at path /webapp/newdb")
  379. }
  380. }
  381. func TestCreateMultipleNames(t *testing.T) {
  382. db, dbpath := newTestDb(t)
  383. defer destroyTestDb(dbpath)
  384. db.Set("/db", "1")
  385. if _, err := db.Set("/myapp", "1"); err != nil {
  386. t.Fatal(err)
  387. }
  388. db.Walk("/", func(p string, e *Entity) error {
  389. t.Logf("%s\n", p)
  390. return nil
  391. }, -1)
  392. }
  393. func TestRefPaths(t *testing.T) {
  394. db, dbpath := newTestDb(t)
  395. defer destroyTestDb(dbpath)
  396. db.Set("/webapp", "1")
  397. db.Set("/db", "2")
  398. db.Set("/webapp/db", "2")
  399. refs := db.RefPaths("2")
  400. if len(refs) != 2 {
  401. t.Fatalf("Expected reference count to be 2, got %d", len(refs))
  402. }
  403. }
  404. func TestExistsTrue(t *testing.T) {
  405. db, dbpath := newTestDb(t)
  406. defer destroyTestDb(dbpath)
  407. db.Set("/testing", "1")
  408. if !db.Exists("/testing") {
  409. t.Fatalf("/tesing should exist")
  410. }
  411. }
  412. func TestExistsFalse(t *testing.T) {
  413. db, dbpath := newTestDb(t)
  414. defer destroyTestDb(dbpath)
  415. db.Set("/toerhe", "1")
  416. if db.Exists("/testing") {
  417. t.Fatalf("/tesing should not exist")
  418. }
  419. }
  420. func TestGetNameWithTrailingSlash(t *testing.T) {
  421. db, dbpath := newTestDb(t)
  422. defer destroyTestDb(dbpath)
  423. db.Set("/todo", "1")
  424. e := db.Get("/todo/")
  425. if e == nil {
  426. t.Fatalf("Entity should not be nil")
  427. }
  428. }
  429. func TestConcurrentWrites(t *testing.T) {
  430. db, dbpath := newTestDb(t)
  431. defer destroyTestDb(dbpath)
  432. errs := make(chan error, 2)
  433. save := func(name string, id string) {
  434. if _, err := db.Set(fmt.Sprintf("/%s", name), id); err != nil {
  435. errs <- err
  436. }
  437. errs <- nil
  438. }
  439. purge := func(id string) {
  440. if _, err := db.Purge(id); err != nil {
  441. errs <- err
  442. }
  443. errs <- nil
  444. }
  445. save("/1", "1")
  446. go purge("1")
  447. go save("/2", "2")
  448. any := false
  449. for i := 0; i < 2; i++ {
  450. if err := <-errs; err != nil {
  451. any = true
  452. t.Log(err)
  453. }
  454. }
  455. if any {
  456. t.Fail()
  457. }
  458. }