graphdb_test.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  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)
  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 TestCreateRootEntity(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("Entity 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 duplicate 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 TestParents(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. for i := 6; i < 11; i++ {
  92. a := strconv.Itoa(i)
  93. p := strconv.Itoa(i - 5)
  94. key := fmt.Sprintf("/%s/%s", p, a)
  95. if _, err := db.Set(key, a); err != nil {
  96. t.Fatal(err)
  97. }
  98. parents, err := db.Parents(key)
  99. if err != nil {
  100. t.Fatal(err)
  101. }
  102. if len(parents) != 1 {
  103. t.Fatalf("Expected 2 entries for %s got %d", key, len(parents))
  104. }
  105. if parents[0] != p {
  106. t.Fatalf("ID %s received, %s expected", parents[0], p)
  107. }
  108. }
  109. }
  110. func TestChildren(t *testing.T) {
  111. db, dbpath := newTestDb(t)
  112. defer destroyTestDb(dbpath)
  113. str := "/"
  114. for i := 1; i < 6; i++ {
  115. a := strconv.Itoa(i)
  116. if _, err := db.Set(str+a, a); err != nil {
  117. t.Fatal(err)
  118. }
  119. str = str + a + "/"
  120. }
  121. str = "/"
  122. for i := 10; i < 30; i++ { // 20 entities
  123. a := strconv.Itoa(i)
  124. if _, err := db.Set(str+a, a); err != nil {
  125. t.Fatal(err)
  126. }
  127. str = str + a + "/"
  128. }
  129. entries, err := db.Children("/", 5)
  130. if err != nil {
  131. t.Fatal(err)
  132. }
  133. if len(entries) != 11 {
  134. t.Fatalf("Expect 11 entries for / got %d", len(entries))
  135. }
  136. entries, err = db.Children("/", 20)
  137. if err != nil {
  138. t.Fatal(err)
  139. }
  140. if len(entries) != 25 {
  141. t.Fatalf("Expect 25 entries for / got %d", len(entries))
  142. }
  143. }
  144. func TestListAllRootChildren(t *testing.T) {
  145. db, dbpath := newTestDb(t)
  146. defer destroyTestDb(dbpath)
  147. for i := 1; i < 6; i++ {
  148. a := strconv.Itoa(i)
  149. if _, err := db.Set("/"+a, a); err != nil {
  150. t.Fatal(err)
  151. }
  152. }
  153. entries := db.List("/", -1)
  154. if len(entries) != 5 {
  155. t.Fatalf("Expect 5 entries for / got %d", len(entries))
  156. }
  157. }
  158. func TestListAllSubChildren(t *testing.T) {
  159. db, dbpath := newTestDb(t)
  160. defer destroyTestDb(dbpath)
  161. _, err := db.Set("/webapp", "1")
  162. if err != nil {
  163. t.Fatal(err)
  164. }
  165. child2, err := db.Set("/db", "2")
  166. if err != nil {
  167. t.Fatal(err)
  168. }
  169. child4, err := db.Set("/logs", "4")
  170. if err != nil {
  171. t.Fatal(err)
  172. }
  173. if _, err := db.Set("/db/logs", child4.ID()); err != nil {
  174. t.Fatal(err)
  175. }
  176. child3, err := db.Set("/sentry", "3")
  177. if err != nil {
  178. t.Fatal(err)
  179. }
  180. if _, err := db.Set("/webapp/sentry", child3.ID()); err != nil {
  181. t.Fatal(err)
  182. }
  183. if _, err := db.Set("/webapp/db", child2.ID()); err != nil {
  184. t.Fatal(err)
  185. }
  186. entries := db.List("/webapp", 1)
  187. if len(entries) != 3 {
  188. t.Fatalf("Expect 3 entries for / got %d", len(entries))
  189. }
  190. entries = db.List("/webapp", 0)
  191. if len(entries) != 2 {
  192. t.Fatalf("Expect 2 entries for / got %d", len(entries))
  193. }
  194. }
  195. func TestAddSelfAsChild(t *testing.T) {
  196. db, dbpath := newTestDb(t)
  197. defer destroyTestDb(dbpath)
  198. child, err := db.Set("/test", "1")
  199. if err != nil {
  200. t.Fatal(err)
  201. }
  202. if _, err := db.Set("/test/other", child.ID()); err == nil {
  203. t.Fatal("Error should not be nil")
  204. }
  205. }
  206. func TestAddChildToNonExistantRoot(t *testing.T) {
  207. db, dbpath := newTestDb(t)
  208. defer destroyTestDb(dbpath)
  209. if _, err := db.Set("/myapp", "1"); err != nil {
  210. t.Fatal(err)
  211. }
  212. if _, err := db.Set("/myapp/proxy/db", "2"); err == nil {
  213. t.Fatal("Error should not be nil")
  214. }
  215. }
  216. func TestWalkAll(t *testing.T) {
  217. db, dbpath := newTestDb(t)
  218. defer destroyTestDb(dbpath)
  219. _, err := db.Set("/webapp", "1")
  220. if err != nil {
  221. t.Fatal(err)
  222. }
  223. child2, err := db.Set("/db", "2")
  224. if err != nil {
  225. t.Fatal(err)
  226. }
  227. child4, err := db.Set("/db/logs", "4")
  228. if err != nil {
  229. t.Fatal(err)
  230. }
  231. if _, err := db.Set("/webapp/logs", child4.ID()); err != nil {
  232. t.Fatal(err)
  233. }
  234. child3, err := db.Set("/sentry", "3")
  235. if err != nil {
  236. t.Fatal(err)
  237. }
  238. if _, err := db.Set("/webapp/sentry", child3.ID()); err != nil {
  239. t.Fatal(err)
  240. }
  241. if _, err := db.Set("/webapp/db", child2.ID()); err != nil {
  242. t.Fatal(err)
  243. }
  244. child5, err := db.Set("/gograph", "5")
  245. if err != nil {
  246. t.Fatal(err)
  247. }
  248. if _, err := db.Set("/webapp/same-ref-diff-name", child5.ID()); err != nil {
  249. t.Fatal(err)
  250. }
  251. if err := db.Walk("/", func(p string, e *Entity) error {
  252. t.Logf("Path: %s Entity: %s", p, e.ID())
  253. return nil
  254. }, -1); err != nil {
  255. t.Fatal(err)
  256. }
  257. }
  258. func TestGetEntityByPath(t *testing.T) {
  259. db, dbpath := newTestDb(t)
  260. defer destroyTestDb(dbpath)
  261. _, err := db.Set("/webapp", "1")
  262. if err != nil {
  263. t.Fatal(err)
  264. }
  265. child2, err := db.Set("/db", "2")
  266. if err != nil {
  267. t.Fatal(err)
  268. }
  269. child4, err := db.Set("/logs", "4")
  270. if err != nil {
  271. t.Fatal(err)
  272. }
  273. if _, err := db.Set("/db/logs", child4.ID()); err != nil {
  274. t.Fatal(err)
  275. }
  276. child3, err := db.Set("/sentry", "3")
  277. if err != nil {
  278. t.Fatal(err)
  279. }
  280. if _, err := db.Set("/webapp/sentry", child3.ID()); err != nil {
  281. t.Fatal(err)
  282. }
  283. if _, err := db.Set("/webapp/db", child2.ID()); err != nil {
  284. t.Fatal(err)
  285. }
  286. child5, err := db.Set("/gograph", "5")
  287. if err != nil {
  288. t.Fatal(err)
  289. }
  290. if _, err := db.Set("/webapp/same-ref-diff-name", child5.ID()); err != nil {
  291. t.Fatal(err)
  292. }
  293. entity := db.Get("/webapp/db/logs")
  294. if entity == nil {
  295. t.Fatal("Entity should not be nil")
  296. }
  297. if entity.ID() != "4" {
  298. t.Fatalf("Expected to get entity with id 4, got %s", entity.ID())
  299. }
  300. }
  301. func TestEnitiesPaths(t *testing.T) {
  302. db, dbpath := newTestDb(t)
  303. defer destroyTestDb(dbpath)
  304. _, err := db.Set("/webapp", "1")
  305. if err != nil {
  306. t.Fatal(err)
  307. }
  308. child2, err := db.Set("/db", "2")
  309. if err != nil {
  310. t.Fatal(err)
  311. }
  312. child4, err := db.Set("/logs", "4")
  313. if err != nil {
  314. t.Fatal(err)
  315. }
  316. if _, err := db.Set("/db/logs", child4.ID()); err != nil {
  317. t.Fatal(err)
  318. }
  319. child3, err := db.Set("/sentry", "3")
  320. if err != nil {
  321. t.Fatal(err)
  322. }
  323. if _, err := db.Set("/webapp/sentry", child3.ID()); err != nil {
  324. t.Fatal(err)
  325. }
  326. if _, err := db.Set("/webapp/db", child2.ID()); err != nil {
  327. t.Fatal(err)
  328. }
  329. child5, err := db.Set("/gograph", "5")
  330. if err != nil {
  331. t.Fatal(err)
  332. }
  333. if _, err := db.Set("/webapp/same-ref-diff-name", child5.ID()); err != nil {
  334. t.Fatal(err)
  335. }
  336. out := db.List("/", -1)
  337. for _, p := range out.Paths() {
  338. t.Log(p)
  339. }
  340. }
  341. func TestDeleteRootEntity(t *testing.T) {
  342. db, dbpath := newTestDb(t)
  343. defer destroyTestDb(dbpath)
  344. if err := db.Delete("/"); err == nil {
  345. t.Fatal("Error should not be nil")
  346. }
  347. }
  348. func TestDeleteEntity(t *testing.T) {
  349. db, dbpath := newTestDb(t)
  350. defer destroyTestDb(dbpath)
  351. _, err := db.Set("/webapp", "1")
  352. if err != nil {
  353. t.Fatal(err)
  354. }
  355. child2, err := db.Set("/db", "2")
  356. if err != nil {
  357. t.Fatal(err)
  358. }
  359. child4, err := db.Set("/logs", "4")
  360. if err != nil {
  361. t.Fatal(err)
  362. }
  363. if _, err := db.Set("/db/logs", child4.ID()); err != nil {
  364. t.Fatal(err)
  365. }
  366. child3, err := db.Set("/sentry", "3")
  367. if err != nil {
  368. t.Fatal(err)
  369. }
  370. if _, err := db.Set("/webapp/sentry", child3.ID()); err != nil {
  371. t.Fatal(err)
  372. }
  373. if _, err := db.Set("/webapp/db", child2.ID()); err != nil {
  374. t.Fatal(err)
  375. }
  376. child5, err := db.Set("/gograph", "5")
  377. if err != nil {
  378. t.Fatal(err)
  379. }
  380. if _, err := db.Set("/webapp/same-ref-diff-name", child5.ID()); err != nil {
  381. t.Fatal(err)
  382. }
  383. if err := db.Delete("/webapp/sentry"); err != nil {
  384. t.Fatal(err)
  385. }
  386. entity := db.Get("/webapp/sentry")
  387. if entity != nil {
  388. t.Fatal("Entity /webapp/sentry should be nil")
  389. }
  390. }
  391. func TestCountRefs(t *testing.T) {
  392. db, dbpath := newTestDb(t)
  393. defer destroyTestDb(dbpath)
  394. db.Set("/webapp", "1")
  395. if db.Refs("1") != 1 {
  396. t.Fatal("Expect reference count to be 1")
  397. }
  398. db.Set("/db", "2")
  399. db.Set("/webapp/db", "2")
  400. if db.Refs("2") != 2 {
  401. t.Fatal("Expect reference count to be 2")
  402. }
  403. }
  404. func TestPurgeId(t *testing.T) {
  405. db, dbpath := newTestDb(t)
  406. defer destroyTestDb(dbpath)
  407. db.Set("/webapp", "1")
  408. if c := db.Refs("1"); c != 1 {
  409. t.Fatalf("Expect reference count to be 1, got %d", c)
  410. }
  411. db.Set("/db", "2")
  412. db.Set("/webapp/db", "2")
  413. count, err := db.Purge("2")
  414. if err != nil {
  415. t.Fatal(err)
  416. }
  417. if count != 2 {
  418. t.Fatalf("Expected 2 references to be removed, got %d", count)
  419. }
  420. }
  421. // Regression test https://github.com/docker/docker/issues/12334
  422. func TestPurgeIdRefPaths(t *testing.T) {
  423. db, dbpath := newTestDb(t)
  424. defer destroyTestDb(dbpath)
  425. db.Set("/webapp", "1")
  426. db.Set("/db", "2")
  427. db.Set("/db/webapp", "1")
  428. if c := db.Refs("1"); c != 2 {
  429. t.Fatalf("Expected 2 reference for webapp, got %d", c)
  430. }
  431. if c := db.Refs("2"); c != 1 {
  432. t.Fatalf("Expected 1 reference for db, got %d", c)
  433. }
  434. if rp := db.RefPaths("2"); len(rp) != 1 {
  435. t.Fatalf("Expected 1 reference path for db, got %d", len(rp))
  436. }
  437. count, err := db.Purge("2")
  438. if err != nil {
  439. t.Fatal(err)
  440. }
  441. if count != 2 {
  442. t.Fatalf("Expected 2 rows to be removed, got %d", count)
  443. }
  444. if c := db.Refs("2"); c != 0 {
  445. t.Fatalf("Expected 0 reference for db, got %d", c)
  446. }
  447. if c := db.Refs("1"); c != 1 {
  448. t.Fatalf("Expected 1 reference for webapp, got %d", c)
  449. }
  450. }
  451. func TestRename(t *testing.T) {
  452. db, dbpath := newTestDb(t)
  453. defer destroyTestDb(dbpath)
  454. db.Set("/webapp", "1")
  455. if db.Refs("1") != 1 {
  456. t.Fatal("Expect reference count to be 1")
  457. }
  458. db.Set("/db", "2")
  459. db.Set("/webapp/db", "2")
  460. if db.Get("/webapp/db") == nil {
  461. t.Fatal("Cannot find entity at path /webapp/db")
  462. }
  463. if err := db.Rename("/webapp/db", "/webapp/newdb"); err != nil {
  464. t.Fatal(err)
  465. }
  466. if db.Get("/webapp/db") != nil {
  467. t.Fatal("Entity should not exist at /webapp/db")
  468. }
  469. if db.Get("/webapp/newdb") == nil {
  470. t.Fatal("Cannot find entity at path /webapp/newdb")
  471. }
  472. }
  473. func TestCreateMultipleNames(t *testing.T) {
  474. db, dbpath := newTestDb(t)
  475. defer destroyTestDb(dbpath)
  476. db.Set("/db", "1")
  477. if _, err := db.Set("/myapp", "1"); err != nil {
  478. t.Fatal(err)
  479. }
  480. db.Walk("/", func(p string, e *Entity) error {
  481. t.Logf("%s\n", p)
  482. return nil
  483. }, -1)
  484. }
  485. func TestRefPaths(t *testing.T) {
  486. db, dbpath := newTestDb(t)
  487. defer destroyTestDb(dbpath)
  488. db.Set("/webapp", "1")
  489. db.Set("/db", "2")
  490. db.Set("/webapp/db", "2")
  491. refs := db.RefPaths("2")
  492. if len(refs) != 2 {
  493. t.Fatalf("Expected reference count to be 2, got %d", len(refs))
  494. }
  495. }
  496. func TestExistsTrue(t *testing.T) {
  497. db, dbpath := newTestDb(t)
  498. defer destroyTestDb(dbpath)
  499. db.Set("/testing", "1")
  500. if !db.Exists("/testing") {
  501. t.Fatalf("/tesing should exist")
  502. }
  503. }
  504. func TestExistsFalse(t *testing.T) {
  505. db, dbpath := newTestDb(t)
  506. defer destroyTestDb(dbpath)
  507. db.Set("/toerhe", "1")
  508. if db.Exists("/testing") {
  509. t.Fatalf("/tesing should not exist")
  510. }
  511. }
  512. func TestGetNameWithTrailingSlash(t *testing.T) {
  513. db, dbpath := newTestDb(t)
  514. defer destroyTestDb(dbpath)
  515. db.Set("/todo", "1")
  516. e := db.Get("/todo/")
  517. if e == nil {
  518. t.Fatalf("Entity should not be nil")
  519. }
  520. }
  521. func TestConcurrentWrites(t *testing.T) {
  522. db, dbpath := newTestDb(t)
  523. defer destroyTestDb(dbpath)
  524. errs := make(chan error, 2)
  525. save := func(name string, id string) {
  526. if _, err := db.Set(fmt.Sprintf("/%s", name), id); err != nil {
  527. errs <- err
  528. }
  529. errs <- nil
  530. }
  531. purge := func(id string) {
  532. if _, err := db.Purge(id); err != nil {
  533. errs <- err
  534. }
  535. errs <- nil
  536. }
  537. save("/1", "1")
  538. go purge("1")
  539. go save("/2", "2")
  540. any := false
  541. for i := 0; i < 2; i++ {
  542. if err := <-errs; err != nil {
  543. any = true
  544. t.Log(err)
  545. }
  546. }
  547. if any {
  548. t.Fail()
  549. }
  550. }