cassandra_test.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. // Copyright (c) 2012 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. "bytes"
  7. "flag"
  8. "reflect"
  9. "sort"
  10. "strings"
  11. "sync"
  12. "testing"
  13. "time"
  14. "tux21b.org/v1/gocql/uuid"
  15. )
  16. var (
  17. flagCluster = flag.String("cluster", "127.0.0.1", "a comma-separated list of host:port tuples")
  18. flagProto = flag.Int("proto", 2, "protcol version")
  19. flagCQL = flag.String("cql", "3.0.0", "CQL version")
  20. )
  21. var initOnce sync.Once
  22. func createSession(t *testing.T) *Session {
  23. cluster := NewCluster(strings.Split(*flagCluster, ",")...)
  24. cluster.ProtoVersion = *flagProto
  25. cluster.CQLVersion = *flagCQL
  26. session, err := cluster.CreateSession()
  27. if err != nil {
  28. t.Fatal("createSession:", err)
  29. }
  30. initOnce.Do(func() {
  31. // Drop and re-create the keyspace once. Different tests should use their own
  32. // individual tables, but can assume that the table does not exist before.
  33. if err := session.Query(`DROP KEYSPACE gocql_test`).Exec(); err != nil {
  34. t.Log("drop keyspace:", err)
  35. }
  36. if err := session.Query(`CREATE KEYSPACE gocql_test
  37. WITH replication = {
  38. 'class' : 'SimpleStrategy',
  39. 'replication_factor' : 1
  40. }`).Exec(); err != nil {
  41. t.Fatal("create keyspace:", err)
  42. }
  43. })
  44. if err := session.Query(`USE gocql_test`).Exec(); err != nil {
  45. t.Fatal("createSession:", err)
  46. }
  47. return session
  48. }
  49. func TestEmptyHosts(t *testing.T) {
  50. cluster := NewCluster()
  51. if session, err := cluster.CreateSession(); err == nil {
  52. session.Close()
  53. t.Error("expected err, got nil")
  54. }
  55. }
  56. func TestCRUD(t *testing.T) {
  57. session := createSession(t)
  58. defer session.Close()
  59. if err := session.Query(`CREATE TABLE page (
  60. title varchar,
  61. revid timeuuid,
  62. body varchar,
  63. views bigint,
  64. protected boolean,
  65. modified timestamp,
  66. tags set<varchar>,
  67. attachments map<varchar, text>,
  68. PRIMARY KEY (title, revid)
  69. )`).Exec(); err != nil {
  70. t.Fatal("create table:", err)
  71. }
  72. for _, page := range pageTestData {
  73. if err := session.Query(`INSERT INTO page
  74. (title, revid, body, views, protected, modified, tags, attachments)
  75. VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
  76. page.Title, page.RevId, page.Body, page.Views, page.Protected,
  77. page.Modified, page.Tags, page.Attachments).Exec(); err != nil {
  78. t.Fatal("insert:", err)
  79. }
  80. }
  81. var count int
  82. if err := session.Query("SELECT COUNT(*) FROM page").Scan(&count); err != nil {
  83. t.Error("select count:", err)
  84. }
  85. if count != len(pageTestData) {
  86. t.Errorf("count: expected %d, got %d\n", len(pageTestData), count)
  87. }
  88. for _, original := range pageTestData {
  89. page := new(Page)
  90. err := session.Query(`SELECT title, revid, body, views, protected, modified,
  91. tags, attachments
  92. FROM page WHERE title = ? AND revid = ? LIMIT 1`,
  93. original.Title, original.RevId).Scan(&page.Title, &page.RevId,
  94. &page.Body, &page.Views, &page.Protected, &page.Modified, &page.Tags,
  95. &page.Attachments)
  96. if err != nil {
  97. t.Error("select page:", err)
  98. continue
  99. }
  100. sort.Sort(sort.StringSlice(page.Tags))
  101. sort.Sort(sort.StringSlice(original.Tags))
  102. if !reflect.DeepEqual(page, original) {
  103. t.Errorf("page: expected %#v, got %#v\n", original, page)
  104. }
  105. }
  106. }
  107. func TestTracing(t *testing.T) {
  108. session := createSession(t)
  109. defer session.Close()
  110. if err := session.Query(`CREATE TABLE trace (id int primary key)`).Exec(); err != nil {
  111. t.Fatal("create:", err)
  112. }
  113. buf := &bytes.Buffer{}
  114. trace := NewTraceWriter(session, buf)
  115. if err := session.Query(`INSERT INTO trace (id) VALUES (?)`, 42).Trace(trace).Exec(); err != nil {
  116. t.Error("insert:", err)
  117. } else if buf.Len() == 0 {
  118. t.Error("insert: failed to obtain any tracing")
  119. }
  120. buf.Reset()
  121. var value int
  122. if err := session.Query(`SELECT id FROM trace WHERE id = ?`, 42).Trace(trace).Scan(&value); err != nil {
  123. t.Error("select:", err)
  124. } else if value != 42 {
  125. t.Errorf("value: expected %d, got %d", 42, value)
  126. } else if buf.Len() == 0 {
  127. t.Error("select: failed to obtain any tracing")
  128. }
  129. }
  130. func TestPaging(t *testing.T) {
  131. if *flagProto == 1 {
  132. t.Skip("Paging not supported. Please use Cassandra >= 2.0")
  133. }
  134. session := createSession(t)
  135. defer session.Close()
  136. if err := session.Query("CREATE TABLE large (id int primary key)").Exec(); err != nil {
  137. t.Fatal("create table:", err)
  138. }
  139. for i := 0; i < 100; i++ {
  140. if err := session.Query("INSERT INTO large (id) VALUES (?)", i).Exec(); err != nil {
  141. t.Fatal("insert:", err)
  142. }
  143. }
  144. iter := session.Query("SELECT id FROM large").PageSize(10).Iter()
  145. var id int
  146. count := 0
  147. for iter.Scan(&id) {
  148. count++
  149. }
  150. if err := iter.Close(); err != nil {
  151. t.Fatal("close:", err)
  152. }
  153. if count != 100 {
  154. t.Fatalf("expected %d, got %d", 100, count)
  155. }
  156. }
  157. func TestCAS(t *testing.T) {
  158. if *flagProto == 1 {
  159. t.Skip("lightweight transactions not supported. Please use Cassandra >= 2.0")
  160. }
  161. session := createSession(t)
  162. defer session.Close()
  163. if err := session.Query(`CREATE TABLE cas_table (
  164. title varchar,
  165. revid timeuuid,
  166. PRIMARY KEY (title, revid)
  167. )`).Exec(); err != nil {
  168. t.Fatal("create:", err)
  169. }
  170. title, revid := "baz", uuid.TimeUUID()
  171. var titleCAS string
  172. var revidCAS uuid.UUID
  173. if applied, err := session.Query(`INSERT INTO cas_table (title, revid)
  174. VALUES (?, ?) IF NOT EXISTS`,
  175. title, revid).ScanCAS(&titleCAS, &revidCAS); err != nil {
  176. t.Fatal("insert:", err)
  177. } else if !applied {
  178. t.Fatal("insert should have been applied")
  179. }
  180. if applied, err := session.Query(`INSERT INTO cas_table (title, revid)
  181. VALUES (?, ?) IF NOT EXISTS`,
  182. title, revid).ScanCAS(&titleCAS, &revidCAS); err != nil {
  183. t.Fatal("insert:", err)
  184. } else if applied {
  185. t.Fatal("insert should not have been applied")
  186. } else if title != titleCAS || revid != revidCAS {
  187. t.Fatalf("expected %s/%v but got %s/%v", title, revid, titleCAS, revidCAS)
  188. }
  189. }
  190. func TestBatch(t *testing.T) {
  191. if *flagProto == 1 {
  192. t.Skip("atomic batches not supported. Please use Cassandra >= 2.0")
  193. }
  194. session := createSession(t)
  195. defer session.Close()
  196. if err := session.Query(`CREATE TABLE batch_table (id int primary key)`).Exec(); err != nil {
  197. t.Fatal("create table:", err)
  198. }
  199. batch := NewBatch(LoggedBatch)
  200. for i := 0; i < 100; i++ {
  201. batch.Query(`INSERT INTO batch_table (id) VALUES (?)`, i)
  202. }
  203. if err := session.ExecuteBatch(batch); err != nil {
  204. t.Fatal("execute batch:", err)
  205. }
  206. count := 0
  207. if err := session.Query(`SELECT COUNT(*) FROM batch_table`).Scan(&count); err != nil {
  208. t.Fatal("select count:", err)
  209. } else if count != 100 {
  210. t.Fatalf("count: expected %d, got %d\n", 100, count)
  211. }
  212. }
  213. type Page struct {
  214. Title string
  215. RevId uuid.UUID
  216. Body string
  217. Views int64
  218. Protected bool
  219. Modified time.Time
  220. Tags []string
  221. Attachments map[string]Attachment
  222. }
  223. type Attachment []byte
  224. var pageTestData = []*Page{
  225. &Page{
  226. Title: "Frontpage",
  227. RevId: uuid.TimeUUID(),
  228. Body: "Welcome to this wiki page!",
  229. Modified: time.Date(2013, time.August, 13, 9, 52, 3, 0, time.UTC),
  230. Tags: []string{"start", "important", "test"},
  231. Attachments: map[string]Attachment{
  232. "logo": Attachment("\x00company logo\x00"),
  233. "favicon": Attachment("favicon.ico"),
  234. },
  235. },
  236. &Page{
  237. Title: "Foobar",
  238. RevId: uuid.TimeUUID(),
  239. Body: "foo::Foo f = new foo::Foo(foo::Foo::INIT);",
  240. Modified: time.Date(2013, time.August, 13, 9, 52, 3, 0, time.UTC),
  241. },
  242. }