wiki_test.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  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 IF EXISTS wiki_page`).Exec(); err != nil {
  51. w.tb.Fatal("CreateSchema:", err)
  52. }
  53. if err := w.session.Query(`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. )`).Exec(); err != nil {
  65. w.tb.Fatal("CreateSchema:", err)
  66. }
  67. }
  68. func (w *WikiTest) CreatePages(n int) {
  69. var page WikiPage
  70. t0 := time.Now()
  71. for i := 0; i < n; i++ {
  72. page.Title = fmt.Sprintf("generated_%d", (i&16)+1)
  73. page.Modified = t0.Add(time.Duration(i-n) * time.Minute)
  74. page.RevId = UUIDFromTime(page.Modified)
  75. page.Body = fmt.Sprintf("text %d", i)
  76. if err := w.InsertPage(&page); err != nil {
  77. w.tb.Error("CreatePages:", err)
  78. }
  79. }
  80. }
  81. func (w *WikiTest) InsertPage(page *WikiPage) error {
  82. return w.session.Query(`INSERT INTO wiki_page
  83. (title, revid, body, views, protected, modified, rating, tags, attachments)
  84. VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
  85. page.Title, page.RevId, page.Body, page.Views, page.Protected,
  86. page.Modified, page.Rating, page.Tags, page.Attachments).Exec()
  87. }
  88. func (w *WikiTest) SelectPage(page *WikiPage, title string, revid UUID) error {
  89. return w.session.Query(`SELECT title, revid, body, views, protected,
  90. modified,tags, attachments, rating
  91. FROM wiki_page WHERE title = ? AND revid = ? LIMIT 1`,
  92. title, revid).Scan(&page.Title, &page.RevId,
  93. &page.Body, &page.Views, &page.Protected, &page.Modified, &page.Tags,
  94. &page.Attachments, &page.Rating)
  95. }
  96. func (w *WikiTest) GetPageCount() int {
  97. var count int
  98. if err := w.session.Query(`SELECT COUNT(*) FROM wiki_page`).Scan(&count); err != nil {
  99. w.tb.Error("GetPageCount", err)
  100. }
  101. return count
  102. }
  103. func TestWikiCreateSchema(t *testing.T) {
  104. session := createSession(t)
  105. defer session.Close()
  106. w := WikiTest{session, t}
  107. w.CreateSchema()
  108. }
  109. func BenchmarkWikiCreateSchema(b *testing.B) {
  110. b.StopTimer()
  111. session := createSession(b)
  112. defer func() {
  113. b.StopTimer()
  114. session.Close()
  115. }()
  116. w := WikiTest{session, b}
  117. b.StartTimer()
  118. for i := 0; i < b.N; i++ {
  119. w.CreateSchema()
  120. }
  121. }
  122. func TestWikiCreatePages(t *testing.T) {
  123. session := createSession(t)
  124. defer session.Close()
  125. w := WikiTest{session, t}
  126. w.CreateSchema()
  127. numPages := 5
  128. w.CreatePages(numPages)
  129. if count := w.GetPageCount(); count != numPages {
  130. t.Errorf("expected %d pages, got %d pages.", numPages, count)
  131. }
  132. }
  133. func BenchmarkWikiCreatePages(b *testing.B) {
  134. b.StopTimer()
  135. session := createSession(b)
  136. defer func() {
  137. b.StopTimer()
  138. session.Close()
  139. }()
  140. w := WikiTest{session, b}
  141. w.CreateSchema()
  142. b.StartTimer()
  143. w.CreatePages(b.N)
  144. }
  145. func BenchmarkWikiSelectAllPages(b *testing.B) {
  146. b.StopTimer()
  147. session := createSession(b)
  148. defer func() {
  149. b.StopTimer()
  150. session.Close()
  151. }()
  152. w := WikiTest{session, b}
  153. w.CreateSchema()
  154. w.CreatePages(100)
  155. b.StartTimer()
  156. var page WikiPage
  157. for i := 0; i < b.N; i++ {
  158. iter := session.Query(`SELECT title, revid, body, views, protected,
  159. modified, tags, attachments, rating
  160. FROM wiki_page`).Iter()
  161. for iter.Scan(&page.Title, &page.RevId, &page.Body, &page.Views,
  162. &page.Protected, &page.Modified, &page.Tags, &page.Attachments,
  163. &page.Rating) {
  164. // pass
  165. }
  166. if err := iter.Close(); err != nil {
  167. b.Error(err)
  168. }
  169. }
  170. }
  171. func BenchmarkWikiSelectSinglePage(b *testing.B) {
  172. b.StopTimer()
  173. session := createSession(b)
  174. defer func() {
  175. b.StopTimer()
  176. session.Close()
  177. }()
  178. w := WikiTest{session, b}
  179. w.CreateSchema()
  180. pages := make([]WikiPage, 100)
  181. w.CreatePages(len(pages))
  182. iter := session.Query(`SELECT title, revid FROM wiki_page`).Iter()
  183. for i := 0; i < len(pages); i++ {
  184. if !iter.Scan(&pages[i].Title, &pages[i].RevId) {
  185. pages = pages[:i]
  186. break
  187. }
  188. }
  189. if err := iter.Close(); err != nil {
  190. b.Error(err)
  191. }
  192. b.StartTimer()
  193. var page WikiPage
  194. for i := 0; i < b.N; i++ {
  195. p := &pages[i%len(pages)]
  196. if err := w.SelectPage(&page, p.Title, p.RevId); err != nil {
  197. b.Error(err)
  198. }
  199. }
  200. }
  201. func BenchmarkWikiSelectPageCount(b *testing.B) {
  202. b.StopTimer()
  203. session := createSession(b)
  204. defer func() {
  205. b.StopTimer()
  206. session.Close()
  207. }()
  208. w := WikiTest{session, b}
  209. w.CreateSchema()
  210. numPages := 10
  211. w.CreatePages(numPages)
  212. b.StartTimer()
  213. for i := 0; i < b.N; i++ {
  214. if count := w.GetPageCount(); count != numPages {
  215. b.Errorf("expected %d pages, got %d pages.", numPages, count)
  216. }
  217. }
  218. }
  219. func TestWikiTypicalCRUD(t *testing.T) {
  220. session := createSession(t)
  221. defer session.Close()
  222. w := WikiTest{session, t}
  223. w.CreateSchema()
  224. for _, page := range wikiTestData {
  225. if err := w.InsertPage(page); err != nil {
  226. t.Error("InsertPage:", err)
  227. }
  228. }
  229. if count := w.GetPageCount(); count != len(wikiTestData) {
  230. t.Errorf("count: expected %d, got %d\n", len(wikiTestData), count)
  231. }
  232. for _, original := range wikiTestData {
  233. page := new(WikiPage)
  234. if err := w.SelectPage(page, original.Title, original.RevId); err != nil {
  235. t.Error("SelectPage:", err)
  236. continue
  237. }
  238. sort.Sort(sort.StringSlice(page.Tags))
  239. sort.Sort(sort.StringSlice(original.Tags))
  240. if !reflect.DeepEqual(page, original) {
  241. t.Errorf("page: expected %#v, got %#v\n", original, page)
  242. }
  243. }
  244. }