cassandra_test.go 7.2 KB

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