wiki_test.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. // Copyright (c) 2014 The gocql Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package gocql
  5. import (
  6. "fmt"
  7. "reflect"
  8. "sort"
  9. "speter.net/go/exp/math/dec/inf"
  10. "testing"
  11. "time"
  12. )
  13. type WikiPage struct {
  14. Title string
  15. RevId UUID
  16. Body string
  17. Views int64
  18. Protected bool
  19. Modified time.Time
  20. Rating *inf.Dec
  21. Tags []string
  22. Attachments map[string]WikiAttachment
  23. }
  24. type WikiAttachment []byte
  25. var wikiTestData = []*WikiPage{
  26. &WikiPage{
  27. Title: "Frontpage",
  28. RevId: TimeUUID(),
  29. Body: "Welcome to this wiki page!",
  30. Rating: inf.NewDec(131, 3),
  31. Modified: time.Date(2013, time.August, 13, 9, 52, 3, 0, time.UTC),
  32. Tags: []string{"start", "important", "test"},
  33. Attachments: map[string]WikiAttachment{
  34. "logo": WikiAttachment("\x00company logo\x00"),
  35. "favicon": WikiAttachment("favicon.ico"),
  36. },
  37. },
  38. &WikiPage{
  39. Title: "Foobar",
  40. RevId: TimeUUID(),
  41. Body: "foo::Foo f = new foo::Foo(foo::Foo::INIT);",
  42. Modified: time.Date(2013, time.August, 13, 9, 52, 3, 0, time.UTC),
  43. },
  44. }
  45. type WikiTest struct {
  46. session *Session
  47. tb testing.TB
  48. }
  49. func (w *WikiTest) CreateSchema() {
  50. if err := w.session.Query(`DROP TABLE wiki_page`).Exec(); err != nil && err.Error() != "unconfigured columnfamily wiki_page" {
  51. w.tb.Fatal("CreateSchema:", err)
  52. }
  53. err := createTable(w.session, `CREATE TABLE wiki_page (
  54. title varchar,
  55. revid timeuuid,
  56. body varchar,
  57. views bigint,
  58. protected boolean,
  59. modified timestamp,
  60. rating decimal,
  61. tags set<varchar>,
  62. attachments map<varchar, blob>,
  63. PRIMARY KEY (title, revid)
  64. )`)
  65. if clusterSize > 1 {
  66. // wait for table definition to propogate
  67. time.Sleep(250 * time.Millisecond)
  68. }
  69. if err != nil {
  70. w.tb.Fatal("CreateSchema:", err)
  71. }
  72. }
  73. func (w *WikiTest) CreatePages(n int) {
  74. var page WikiPage
  75. t0 := time.Now()
  76. for i := 0; i < n; i++ {
  77. page.Title = fmt.Sprintf("generated_%d", (i&16)+1)
  78. page.Modified = t0.Add(time.Duration(i-n) * time.Minute)
  79. page.RevId = UUIDFromTime(page.Modified)
  80. page.Body = fmt.Sprintf("text %d", i)
  81. if err := w.InsertPage(&page); err != nil {
  82. w.tb.Error("CreatePages:", err)
  83. }
  84. }
  85. }
  86. func (w *WikiTest) InsertPage(page *WikiPage) error {
  87. return w.session.Query(`INSERT INTO wiki_page
  88. (title, revid, body, views, protected, modified, rating, tags, attachments)
  89. VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
  90. page.Title, page.RevId, page.Body, page.Views, page.Protected,
  91. page.Modified, page.Rating, page.Tags, page.Attachments).Exec()
  92. }
  93. func (w *WikiTest) SelectPage(page *WikiPage, title string, revid UUID) error {
  94. return w.session.Query(`SELECT title, revid, body, views, protected,
  95. modified,tags, attachments, rating
  96. FROM wiki_page WHERE title = ? AND revid = ? LIMIT 1`,
  97. title, revid).Scan(&page.Title, &page.RevId,
  98. &page.Body, &page.Views, &page.Protected, &page.Modified, &page.Tags,
  99. &page.Attachments, &page.Rating)
  100. }
  101. func (w *WikiTest) GetPageCount() int {
  102. var count int
  103. if err := w.session.Query(`SELECT COUNT(*) FROM wiki_page`).Scan(&count); err != nil {
  104. w.tb.Error("GetPageCount", err)
  105. }
  106. return count
  107. }
  108. func TestWikiCreateSchema(t *testing.T) {
  109. session := createSession(t)
  110. defer session.Close()
  111. w := WikiTest{session, t}
  112. w.CreateSchema()
  113. }
  114. func BenchmarkWikiCreateSchema(b *testing.B) {
  115. b.StopTimer()
  116. session := createSession(b)
  117. defer func() {
  118. b.StopTimer()
  119. session.Close()
  120. }()
  121. w := WikiTest{session, b}
  122. b.StartTimer()
  123. for i := 0; i < b.N; i++ {
  124. w.CreateSchema()
  125. }
  126. }
  127. func TestWikiCreatePages(t *testing.T) {
  128. session := createSession(t)
  129. defer session.Close()
  130. w := WikiTest{session, t}
  131. w.CreateSchema()
  132. numPages := 5
  133. w.CreatePages(numPages)
  134. if count := w.GetPageCount(); count != numPages {
  135. t.Errorf("expected %d pages, got %d pages.", numPages, count)
  136. }
  137. }
  138. func BenchmarkWikiCreatePages(b *testing.B) {
  139. b.StopTimer()
  140. session := createSession(b)
  141. defer func() {
  142. b.StopTimer()
  143. session.Close()
  144. }()
  145. w := WikiTest{session, b}
  146. w.CreateSchema()
  147. b.StartTimer()
  148. w.CreatePages(b.N)
  149. }
  150. func BenchmarkWikiSelectAllPages(b *testing.B) {
  151. b.StopTimer()
  152. session := createSession(b)
  153. defer func() {
  154. b.StopTimer()
  155. session.Close()
  156. }()
  157. w := WikiTest{session, b}
  158. w.CreateSchema()
  159. w.CreatePages(100)
  160. b.StartTimer()
  161. var page WikiPage
  162. for i := 0; i < b.N; i++ {
  163. iter := session.Query(`SELECT title, revid, body, views, protected,
  164. modified, tags, attachments, rating
  165. FROM wiki_page`).Iter()
  166. for iter.Scan(&page.Title, &page.RevId, &page.Body, &page.Views,
  167. &page.Protected, &page.Modified, &page.Tags, &page.Attachments,
  168. &page.Rating) {
  169. // pass
  170. }
  171. if err := iter.Close(); err != nil {
  172. b.Error(err)
  173. }
  174. }
  175. }
  176. func BenchmarkWikiSelectSinglePage(b *testing.B) {
  177. b.StopTimer()
  178. session := createSession(b)
  179. defer func() {
  180. b.StopTimer()
  181. session.Close()
  182. }()
  183. w := WikiTest{session, b}
  184. w.CreateSchema()
  185. pages := make([]WikiPage, 100)
  186. w.CreatePages(len(pages))
  187. iter := session.Query(`SELECT title, revid FROM wiki_page`).Iter()
  188. for i := 0; i < len(pages); i++ {
  189. if !iter.Scan(&pages[i].Title, &pages[i].RevId) {
  190. pages = pages[:i]
  191. break
  192. }
  193. }
  194. if err := iter.Close(); err != nil {
  195. b.Error(err)
  196. }
  197. b.StartTimer()
  198. var page WikiPage
  199. for i := 0; i < b.N; i++ {
  200. p := &pages[i%len(pages)]
  201. if err := w.SelectPage(&page, p.Title, p.RevId); err != nil {
  202. b.Error(err)
  203. }
  204. }
  205. }
  206. func BenchmarkWikiSelectPageCount(b *testing.B) {
  207. b.StopTimer()
  208. session := createSession(b)
  209. defer func() {
  210. b.StopTimer()
  211. session.Close()
  212. }()
  213. w := WikiTest{session, b}
  214. w.CreateSchema()
  215. numPages := 10
  216. w.CreatePages(numPages)
  217. b.StartTimer()
  218. for i := 0; i < b.N; i++ {
  219. if count := w.GetPageCount(); count != numPages {
  220. b.Errorf("expected %d pages, got %d pages.", numPages, count)
  221. }
  222. }
  223. }
  224. func TestWikiTypicalCRUD(t *testing.T) {
  225. session := createSession(t)
  226. defer session.Close()
  227. w := WikiTest{session, t}
  228. w.CreateSchema()
  229. for _, page := range wikiTestData {
  230. if err := w.InsertPage(page); err != nil {
  231. t.Error("InsertPage:", err)
  232. }
  233. }
  234. if count := w.GetPageCount(); count != len(wikiTestData) {
  235. t.Errorf("count: expected %d, got %d\n", len(wikiTestData), count)
  236. }
  237. for _, original := range wikiTestData {
  238. page := new(WikiPage)
  239. if err := w.SelectPage(page, original.Title, original.RevId); err != nil {
  240. t.Error("SelectPage:", err)
  241. continue
  242. }
  243. sort.Sort(sort.StringSlice(page.Tags))
  244. sort.Sort(sort.StringSlice(original.Tags))
  245. if !reflect.DeepEqual(page, original) {
  246. t.Errorf("page: expected %#v, got %#v\n", original, page)
  247. }
  248. }
  249. }