metadata_test.go 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670
  1. // Copyright (c) 2015 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. "strconv"
  7. "testing"
  8. )
  9. func TestCompileMetadata(t *testing.T) {
  10. // V1 tests - these are all based on real examples from the integration test ccm cluster
  11. keyspace := &KeyspaceMetadata{
  12. Name: "V1Keyspace",
  13. }
  14. tables := []TableMetadata{
  15. TableMetadata{
  16. // This table, found in the system keyspace, has no key aliases or column aliases
  17. Keyspace: "V1Keyspace",
  18. Name: "Schema",
  19. KeyValidator: "org.apache.cassandra.db.marshal.BytesType",
  20. Comparator: "org.apache.cassandra.db.marshal.UTF8Type",
  21. DefaultValidator: "org.apache.cassandra.db.marshal.BytesType",
  22. KeyAliases: []string{},
  23. ColumnAliases: []string{},
  24. ValueAlias: "",
  25. },
  26. TableMetadata{
  27. // This table, found in the system keyspace, has key aliases, column aliases, and a value alias.
  28. Keyspace: "V1Keyspace",
  29. Name: "hints",
  30. KeyValidator: "org.apache.cassandra.db.marshal.UUIDType",
  31. Comparator: "org.apache.cassandra.db.marshal.CompositeType(org.apache.cassandra.db.marshal.TimeUUIDType,org.apache.cassandra.db.marshal.Int32Type)",
  32. DefaultValidator: "org.apache.cassandra.db.marshal.BytesType",
  33. KeyAliases: []string{"target_id"},
  34. ColumnAliases: []string{"hint_id", "message_version"},
  35. ValueAlias: "mutation",
  36. },
  37. TableMetadata{
  38. // This table, found in the system keyspace, has a comparator with collections, but no column aliases
  39. Keyspace: "V1Keyspace",
  40. Name: "peers",
  41. KeyValidator: "org.apache.cassandra.db.marshal.InetAddressType",
  42. Comparator: "org.apache.cassandra.db.marshal.CompositeType(org.apache.cassandra.db.marshal.UTF8Type,org.apache.cassandra.db.marshal.ColumnToCollectionType(746f6b656e73:org.apache.cassandra.db.marshal.SetType(org.apache.cassandra.db.marshal.UTF8Type)))",
  43. DefaultValidator: "org.apache.cassandra.db.marshal.BytesType",
  44. KeyAliases: []string{"peer"},
  45. ColumnAliases: []string{},
  46. ValueAlias: "",
  47. },
  48. TableMetadata{
  49. // This table, found in the system keyspace, has a column alias, but not a composite comparator
  50. Keyspace: "V1Keyspace",
  51. Name: "IndexInfo",
  52. KeyValidator: "org.apache.cassandra.db.marshal.UTF8Type",
  53. Comparator: "org.apache.cassandra.db.marshal.UTF8Type",
  54. DefaultValidator: "org.apache.cassandra.db.marshal.BytesType",
  55. KeyAliases: []string{"table_name"},
  56. ColumnAliases: []string{"index_name"},
  57. ValueAlias: "",
  58. },
  59. TableMetadata{
  60. // This table, found in the gocql_test keyspace following an integration test run, has a composite comparator with collections as well as a column alias
  61. Keyspace: "V1Keyspace",
  62. Name: "wiki_page",
  63. KeyValidator: "org.apache.cassandra.db.marshal.UTF8Type",
  64. Comparator: "org.apache.cassandra.db.marshal.CompositeType(org.apache.cassandra.db.marshal.TimeUUIDType,org.apache.cassandra.db.marshal.UTF8Type,org.apache.cassandra.db.marshal.ColumnToCollectionType(74616773:org.apache.cassandra.db.marshal.SetType(org.apache.cassandra.db.marshal.UTF8Type),6174746163686d656e7473:org.apache.cassandra.db.marshal.MapType(org.apache.cassandra.db.marshal.UTF8Type,org.apache.cassandra.db.marshal.BytesType)))",
  65. DefaultValidator: "org.apache.cassandra.db.marshal.BytesType",
  66. KeyAliases: []string{"title"},
  67. ColumnAliases: []string{"revid"},
  68. ValueAlias: "",
  69. },
  70. }
  71. columns := []ColumnMetadata{
  72. // Here are the regular columns from the peers table for testing regular columns
  73. ColumnMetadata{Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "data_center", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type"},
  74. ColumnMetadata{Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "host_id", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UUIDType"},
  75. ColumnMetadata{Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "rack", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type"},
  76. ColumnMetadata{Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "release_version", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type"},
  77. ColumnMetadata{Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "rpc_address", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.InetAddressType"},
  78. ColumnMetadata{Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "schema_version", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UUIDType"},
  79. ColumnMetadata{Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "tokens", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.SetType(org.apache.cassandra.db.marshal.UTF8Type)"},
  80. }
  81. compileMetadata(1, keyspace, tables, columns)
  82. assertKeyspaceMetadata(
  83. t,
  84. keyspace,
  85. &KeyspaceMetadata{
  86. Name: "V1Keyspace",
  87. Tables: map[string]*TableMetadata{
  88. "Schema": &TableMetadata{
  89. PartitionKey: []*ColumnMetadata{
  90. &ColumnMetadata{
  91. Name: "key",
  92. Type: TypeInfo{Type: TypeBlob},
  93. },
  94. },
  95. ClusteringColumns: []*ColumnMetadata{},
  96. Columns: map[string]*ColumnMetadata{
  97. "key": &ColumnMetadata{
  98. Name: "key",
  99. Type: TypeInfo{Type: TypeBlob},
  100. Kind: PARTITION_KEY,
  101. },
  102. },
  103. },
  104. "hints": &TableMetadata{
  105. PartitionKey: []*ColumnMetadata{
  106. &ColumnMetadata{
  107. Name: "target_id",
  108. Type: TypeInfo{Type: TypeUUID},
  109. },
  110. },
  111. ClusteringColumns: []*ColumnMetadata{
  112. &ColumnMetadata{
  113. Name: "hint_id",
  114. Type: TypeInfo{Type: TypeTimeUUID},
  115. Order: ASC,
  116. },
  117. &ColumnMetadata{
  118. Name: "message_version",
  119. Type: TypeInfo{Type: TypeInt},
  120. Order: ASC,
  121. },
  122. },
  123. Columns: map[string]*ColumnMetadata{
  124. "target_id": &ColumnMetadata{
  125. Name: "target_id",
  126. Type: TypeInfo{Type: TypeUUID},
  127. Kind: PARTITION_KEY,
  128. },
  129. "hint_id": &ColumnMetadata{
  130. Name: "hint_id",
  131. Type: TypeInfo{Type: TypeTimeUUID},
  132. Order: ASC,
  133. Kind: CLUSTERING_KEY,
  134. },
  135. "message_version": &ColumnMetadata{
  136. Name: "message_version",
  137. Type: TypeInfo{Type: TypeInt},
  138. Order: ASC,
  139. Kind: CLUSTERING_KEY,
  140. },
  141. "mutation": &ColumnMetadata{
  142. Name: "mutation",
  143. Type: TypeInfo{Type: TypeBlob},
  144. Kind: REGULAR,
  145. },
  146. },
  147. },
  148. "peers": &TableMetadata{
  149. PartitionKey: []*ColumnMetadata{
  150. &ColumnMetadata{
  151. Name: "peer",
  152. Type: TypeInfo{Type: TypeInet},
  153. },
  154. },
  155. ClusteringColumns: []*ColumnMetadata{},
  156. Columns: map[string]*ColumnMetadata{
  157. "peer": &ColumnMetadata{
  158. Name: "peer",
  159. Type: TypeInfo{Type: TypeInet},
  160. Kind: PARTITION_KEY,
  161. },
  162. "data_center": &ColumnMetadata{Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "data_center", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type", Type: TypeInfo{Type: TypeVarchar}},
  163. "host_id": &ColumnMetadata{Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "host_id", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UUIDType", Type: TypeInfo{Type: TypeUUID}},
  164. "rack": &ColumnMetadata{Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "rack", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type", Type: TypeInfo{Type: TypeVarchar}},
  165. "release_version": &ColumnMetadata{Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "release_version", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type", Type: TypeInfo{Type: TypeVarchar}},
  166. "rpc_address": &ColumnMetadata{Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "rpc_address", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.InetAddressType", Type: TypeInfo{Type: TypeInet}},
  167. "schema_version": &ColumnMetadata{Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "schema_version", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UUIDType", Type: TypeInfo{Type: TypeUUID}},
  168. "tokens": &ColumnMetadata{Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "tokens", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.SetType(org.apache.cassandra.db.marshal.UTF8Type)", Type: TypeInfo{Type: TypeSet}},
  169. },
  170. },
  171. "IndexInfo": &TableMetadata{
  172. PartitionKey: []*ColumnMetadata{
  173. &ColumnMetadata{
  174. Name: "table_name",
  175. Type: TypeInfo{Type: TypeVarchar},
  176. },
  177. },
  178. ClusteringColumns: []*ColumnMetadata{
  179. &ColumnMetadata{
  180. Name: "index_name",
  181. Type: TypeInfo{Type: TypeVarchar},
  182. Order: ASC,
  183. },
  184. },
  185. Columns: map[string]*ColumnMetadata{
  186. "table_name": &ColumnMetadata{
  187. Name: "table_name",
  188. Type: TypeInfo{Type: TypeVarchar},
  189. Kind: PARTITION_KEY,
  190. },
  191. "index_name": &ColumnMetadata{
  192. Name: "index_name",
  193. Type: TypeInfo{Type: TypeVarchar},
  194. Kind: CLUSTERING_KEY,
  195. },
  196. "value": &ColumnMetadata{
  197. Name: "value",
  198. Type: TypeInfo{Type: TypeBlob},
  199. Kind: REGULAR,
  200. },
  201. },
  202. },
  203. "wiki_page": &TableMetadata{
  204. PartitionKey: []*ColumnMetadata{
  205. &ColumnMetadata{
  206. Name: "title",
  207. Type: TypeInfo{Type: TypeVarchar},
  208. },
  209. },
  210. ClusteringColumns: []*ColumnMetadata{
  211. &ColumnMetadata{
  212. Name: "revid",
  213. Type: TypeInfo{Type: TypeTimeUUID},
  214. Order: ASC,
  215. },
  216. },
  217. Columns: map[string]*ColumnMetadata{
  218. "title": &ColumnMetadata{
  219. Name: "title",
  220. Type: TypeInfo{Type: TypeVarchar},
  221. Kind: PARTITION_KEY,
  222. },
  223. "revid": &ColumnMetadata{
  224. Name: "revid",
  225. Type: TypeInfo{Type: TypeTimeUUID},
  226. Kind: CLUSTERING_KEY,
  227. },
  228. },
  229. },
  230. },
  231. },
  232. )
  233. // V2 test - V2+ protocol is simpler so here are some toy examples to verify that the mapping works
  234. keyspace = &KeyspaceMetadata{
  235. Name: "V2Keyspace",
  236. }
  237. tables = []TableMetadata{
  238. TableMetadata{
  239. Keyspace: "V2Keyspace",
  240. Name: "Table1",
  241. },
  242. TableMetadata{
  243. Keyspace: "V2Keyspace",
  244. Name: "Table2",
  245. },
  246. }
  247. columns = []ColumnMetadata{
  248. ColumnMetadata{
  249. Keyspace: "V2Keyspace",
  250. Table: "Table1",
  251. Name: "Key1",
  252. Kind: PARTITION_KEY,
  253. Validator: "org.apache.cassandra.db.marshal.UTF8Type",
  254. },
  255. ColumnMetadata{
  256. Keyspace: "V2Keyspace",
  257. Table: "Table2",
  258. Name: "Column1",
  259. Kind: PARTITION_KEY,
  260. Validator: "org.apache.cassandra.db.marshal.UTF8Type",
  261. },
  262. ColumnMetadata{
  263. Keyspace: "V2Keyspace",
  264. Table: "Table2",
  265. Name: "Column2",
  266. Kind: CLUSTERING_KEY,
  267. Validator: "org.apache.cassandra.db.marshal.UTF8Type",
  268. },
  269. ColumnMetadata{
  270. Keyspace: "V2Keyspace",
  271. Table: "Table2",
  272. Name: "Column3",
  273. Kind: REGULAR,
  274. Validator: "org.apache.cassandra.db.marshal.UTF8Type",
  275. },
  276. }
  277. compileMetadata(2, keyspace, tables, columns)
  278. assertKeyspaceMetadata(
  279. t,
  280. keyspace,
  281. &KeyspaceMetadata{
  282. Name: "V2Keyspace",
  283. Tables: map[string]*TableMetadata{
  284. "Table1": &TableMetadata{
  285. PartitionKey: []*ColumnMetadata{
  286. &ColumnMetadata{
  287. Name: "Key1",
  288. Type: TypeInfo{Type: TypeVarchar},
  289. },
  290. },
  291. ClusteringColumns: []*ColumnMetadata{},
  292. Columns: map[string]*ColumnMetadata{
  293. "Key1": &ColumnMetadata{
  294. Name: "Key1",
  295. Type: TypeInfo{Type: TypeVarchar},
  296. Kind: PARTITION_KEY,
  297. },
  298. },
  299. },
  300. "Table2": &TableMetadata{
  301. PartitionKey: []*ColumnMetadata{
  302. &ColumnMetadata{
  303. Name: "Column1",
  304. Type: TypeInfo{Type: TypeVarchar},
  305. },
  306. },
  307. ClusteringColumns: []*ColumnMetadata{
  308. &ColumnMetadata{
  309. Name: "Column2",
  310. Type: TypeInfo{Type: TypeVarchar},
  311. },
  312. },
  313. Columns: map[string]*ColumnMetadata{
  314. "Column1": &ColumnMetadata{
  315. Name: "Column1",
  316. Type: TypeInfo{Type: TypeVarchar},
  317. Kind: PARTITION_KEY,
  318. },
  319. "Column2": &ColumnMetadata{
  320. Name: "Column2",
  321. Type: TypeInfo{Type: TypeVarchar},
  322. Kind: CLUSTERING_KEY,
  323. },
  324. "Column3": &ColumnMetadata{
  325. Name: "Column3",
  326. Type: TypeInfo{Type: TypeVarchar},
  327. Kind: REGULAR,
  328. },
  329. },
  330. },
  331. },
  332. },
  333. )
  334. }
  335. func assertKeyspaceMetadata(t *testing.T, actual, expected *KeyspaceMetadata) {
  336. if len(expected.Tables) != len(actual.Tables) {
  337. t.Errorf("Expected len(%s.Tables) to be %v but was %v", expected.Name, len(expected.Tables), len(actual.Tables))
  338. }
  339. for keyT := range expected.Tables {
  340. et := expected.Tables[keyT]
  341. at, found := actual.Tables[keyT]
  342. if !found {
  343. t.Errorf("Expected %s.Tables[%s] but was not found", expected.Name, keyT)
  344. } else {
  345. if keyT != at.Name {
  346. t.Errorf("Expected %s.Tables[%s].Name to be %v but was %v", expected.Name, keyT, keyT, at.Name)
  347. }
  348. if len(et.PartitionKey) != len(at.PartitionKey) {
  349. t.Errorf("Expected len(%s.Tables[%s].PartitionKey) to be %v but was %v", expected.Name, keyT, len(et.PartitionKey), len(at.PartitionKey))
  350. } else {
  351. for i := range et.PartitionKey {
  352. if et.PartitionKey[i].Name != at.PartitionKey[i].Name {
  353. t.Errorf("Expected %s.Tables[%s].PartitionKey[%d].Name to be '%v' but was '%v'", expected.Name, keyT, i, et.PartitionKey[i].Name, at.PartitionKey[i].Name)
  354. }
  355. if expected.Name != at.PartitionKey[i].Keyspace {
  356. t.Errorf("Expected %s.Tables[%s].PartitionKey[%d].Keyspace to be '%v' but was '%v'", expected.Name, keyT, i, expected.Name, at.PartitionKey[i].Keyspace)
  357. }
  358. if keyT != at.PartitionKey[i].Table {
  359. t.Errorf("Expected %s.Tables[%s].PartitionKey[%d].Table to be '%v' but was '%v'", expected.Name, keyT, i, keyT, at.PartitionKey[i].Table)
  360. }
  361. if et.PartitionKey[i].Type.Type != at.PartitionKey[i].Type.Type {
  362. t.Errorf("Expected %s.Tables[%s].PartitionKey[%d].Type.Type to be %v but was %v", expected.Name, keyT, i, et.PartitionKey[i].Type.Type, at.PartitionKey[i].Type.Type)
  363. }
  364. if i != at.PartitionKey[i].ComponentIndex {
  365. t.Errorf("Expected %s.Tables[%s].PartitionKey[%d].ComponentIndex to be %v but was %v", expected.Name, keyT, i, i, at.PartitionKey[i].ComponentIndex)
  366. }
  367. if PARTITION_KEY != at.PartitionKey[i].Kind {
  368. t.Errorf("Expected %s.Tables[%s].PartitionKey[%d].Kind to be '%v' but was '%v'", expected.Name, keyT, i, PARTITION_KEY, at.PartitionKey[i].Kind)
  369. }
  370. }
  371. }
  372. if len(et.ClusteringColumns) != len(at.ClusteringColumns) {
  373. t.Errorf("Expected len(%s.Tables[%s].ClusteringColumns) to be %v but was %v", expected.Name, keyT, len(et.ClusteringColumns), len(at.ClusteringColumns))
  374. } else {
  375. for i := range et.ClusteringColumns {
  376. if et.ClusteringColumns[i].Name != at.ClusteringColumns[i].Name {
  377. t.Errorf("Expected %s.Tables[%s].ClusteringColumns[%d].Name to be '%v' but was '%v'", expected.Name, keyT, i, et.ClusteringColumns[i].Name, at.ClusteringColumns[i].Name)
  378. }
  379. if expected.Name != at.ClusteringColumns[i].Keyspace {
  380. t.Errorf("Expected %s.Tables[%s].ClusteringColumns[%d].Keyspace to be '%v' but was '%v'", expected.Name, keyT, i, expected.Name, at.ClusteringColumns[i].Keyspace)
  381. }
  382. if keyT != at.ClusteringColumns[i].Table {
  383. t.Errorf("Expected %s.Tables[%s].ClusteringColumns[%d].Table to be '%v' but was '%v'", expected.Name, keyT, i, keyT, at.ClusteringColumns[i].Table)
  384. }
  385. if et.ClusteringColumns[i].Type.Type != at.ClusteringColumns[i].Type.Type {
  386. t.Errorf("Expected %s.Tables[%s].ClusteringColumns[%d].Type.Type to be %v but was %v", expected.Name, keyT, i, et.ClusteringColumns[i].Type.Type, at.ClusteringColumns[i].Type.Type)
  387. }
  388. if i != at.ClusteringColumns[i].ComponentIndex {
  389. t.Errorf("Expected %s.Tables[%s].ClusteringColumns[%d].ComponentIndex to be %v but was %v", expected.Name, keyT, i, i, at.ClusteringColumns[i].ComponentIndex)
  390. }
  391. if et.ClusteringColumns[i].Order != at.ClusteringColumns[i].Order {
  392. t.Errorf("Expected %s.Tables[%s].ClusteringColumns[%d].Order to be %v but was %v", expected.Name, keyT, i, et.ClusteringColumns[i].Order, at.ClusteringColumns[i].Order)
  393. }
  394. if CLUSTERING_KEY != at.ClusteringColumns[i].Kind {
  395. t.Errorf("Expected %s.Tables[%s].ClusteringColumns[%d].Kind to be '%v' but was '%v'", expected.Name, keyT, i, CLUSTERING_KEY, at.ClusteringColumns[i].Kind)
  396. }
  397. }
  398. }
  399. if len(et.Columns) != len(at.Columns) {
  400. eKeys := make([]string, 0, len(et.Columns))
  401. for key := range et.Columns {
  402. eKeys = append(eKeys, key)
  403. }
  404. aKeys := make([]string, 0, len(at.Columns))
  405. for key := range at.Columns {
  406. aKeys = append(aKeys, key)
  407. }
  408. t.Errorf("Expected len(%s.Tables[%s].Columns) to be %v (keys:%v) but was %v (keys:%v)", expected.Name, keyT, len(et.Columns), eKeys, len(at.Columns), aKeys)
  409. } else {
  410. for keyC := range et.Columns {
  411. ec := et.Columns[keyC]
  412. ac, found := at.Columns[keyC]
  413. if !found {
  414. t.Errorf("Expected %s.Tables[%s].Columns[%s] but was not found", expected.Name, keyT, keyC)
  415. } else {
  416. if keyC != ac.Name {
  417. t.Errorf("Expected %s.Tables[%s].Columns[%s].Name to be '%v' but was '%v'", expected.Name, keyT, keyC, keyC, at.Name)
  418. }
  419. if expected.Name != ac.Keyspace {
  420. t.Errorf("Expected %s.Tables[%s].Columns[%s].Keyspace to be '%v' but was '%v'", expected.Name, keyT, keyC, expected.Name, ac.Keyspace)
  421. }
  422. if keyT != ac.Table {
  423. t.Errorf("Expected %s.Tables[%s].Columns[%s].Table to be '%v' but was '%v'", expected.Name, keyT, keyC, keyT, ac.Table)
  424. }
  425. if ec.Type.Type != ac.Type.Type {
  426. t.Errorf("Expected %s.Tables[%s].Columns[%s].Type.Type to be %v but was %v", expected.Name, keyT, keyC, ec.Type.Type, ac.Type.Type)
  427. }
  428. if ec.Order != ac.Order {
  429. t.Errorf("Expected %s.Tables[%s].Columns[%s].Order to be %v but was %v", expected.Name, keyT, keyC, ec.Order, ac.Order)
  430. }
  431. if ec.Kind != ac.Kind {
  432. t.Errorf("Expected %s.Tables[%s].Columns[%s].Kind to be '%v' but was '%v'", expected.Name, keyT, keyC, ec.Kind, ac.Kind)
  433. }
  434. }
  435. }
  436. }
  437. }
  438. }
  439. }
  440. func TestTypeParser(t *testing.T) {
  441. // native type
  442. assertParseNonCompositeType(
  443. t,
  444. "org.apache.cassandra.db.marshal.UTF8Type",
  445. assertTypeInfo{Type: TypeVarchar},
  446. )
  447. // reversed
  448. assertParseNonCompositeType(
  449. t,
  450. "org.apache.cassandra.db.marshal.ReversedType(org.apache.cassandra.db.marshal.UUIDType)",
  451. assertTypeInfo{Type: TypeUUID, Reversed: true},
  452. )
  453. // set
  454. assertParseNonCompositeType(
  455. t,
  456. "org.apache.cassandra.db.marshal.SetType(org.apache.cassandra.db.marshal.Int32Type)",
  457. assertTypeInfo{
  458. Type: TypeSet,
  459. Elem: &assertTypeInfo{Type: TypeInt},
  460. },
  461. )
  462. // map
  463. assertParseNonCompositeType(
  464. t,
  465. "org.apache.cassandra.db.marshal.MapType(org.apache.cassandra.db.marshal.UUIDType,org.apache.cassandra.db.marshal.BytesType)",
  466. assertTypeInfo{
  467. Type: TypeMap,
  468. Key: &assertTypeInfo{Type: TypeUUID},
  469. Elem: &assertTypeInfo{Type: TypeBlob},
  470. },
  471. )
  472. // custom
  473. assertParseNonCompositeType(
  474. t,
  475. "org.apache.cassandra.db.marshal.DynamicCompositeType(u=>org.apache.cassandra.db.marshal.UUIDType,d=>org.apache.cassandra.db.marshal.DateType,t=>org.apache.cassandra.db.marshal.TimeUUIDType,b=>org.apache.cassandra.db.marshal.BytesType,s=>org.apache.cassandra.db.marshal.UTF8Type,B=>org.apache.cassandra.db.marshal.BooleanType,a=>org.apache.cassandra.db.marshal.AsciiType,l=>org.apache.cassandra.db.marshal.LongType,i=>org.apache.cassandra.db.marshal.IntegerType,x=>org.apache.cassandra.db.marshal.LexicalUUIDType)",
  476. assertTypeInfo{Type: TypeCustom, Custom: "org.apache.cassandra.db.marshal.DynamicCompositeType(u=>org.apache.cassandra.db.marshal.UUIDType,d=>org.apache.cassandra.db.marshal.DateType,t=>org.apache.cassandra.db.marshal.TimeUUIDType,b=>org.apache.cassandra.db.marshal.BytesType,s=>org.apache.cassandra.db.marshal.UTF8Type,B=>org.apache.cassandra.db.marshal.BooleanType,a=>org.apache.cassandra.db.marshal.AsciiType,l=>org.apache.cassandra.db.marshal.LongType,i=>org.apache.cassandra.db.marshal.IntegerType,x=>org.apache.cassandra.db.marshal.LexicalUUIDType)"},
  477. )
  478. // composite defs
  479. assertParseCompositeType(
  480. t,
  481. "org.apache.cassandra.db.marshal.CompositeType(org.apache.cassandra.db.marshal.UTF8Type)",
  482. []assertTypeInfo{
  483. assertTypeInfo{Type: TypeVarchar},
  484. },
  485. nil,
  486. )
  487. assertParseCompositeType(
  488. t,
  489. "org.apache.cassandra.db.marshal.CompositeType(org.apache.cassandra.db.marshal.DateType,org.apache.cassandra.db.marshal.UTF8Type)",
  490. []assertTypeInfo{
  491. assertTypeInfo{Type: TypeTimestamp},
  492. assertTypeInfo{Type: TypeVarchar},
  493. },
  494. nil,
  495. )
  496. assertParseCompositeType(
  497. t,
  498. "org.apache.cassandra.db.marshal.CompositeType(org.apache.cassandra.db.marshal.UTF8Type,org.apache.cassandra.db.marshal.ColumnToCollectionType(726f77735f6d6572676564:org.apache.cassandra.db.marshal.MapType(org.apache.cassandra.db.marshal.Int32Type,org.apache.cassandra.db.marshal.LongType)))",
  499. []assertTypeInfo{
  500. assertTypeInfo{Type: TypeVarchar},
  501. },
  502. map[string]assertTypeInfo{
  503. "rows_merged": assertTypeInfo{
  504. Type: TypeMap,
  505. Key: &assertTypeInfo{Type: TypeInt},
  506. Elem: &assertTypeInfo{Type: TypeBigInt},
  507. },
  508. },
  509. )
  510. }
  511. //---------------------------------------
  512. // some code to assert the parser result
  513. //---------------------------------------
  514. type assertTypeInfo struct {
  515. Type Type
  516. Reversed bool
  517. Elem *assertTypeInfo
  518. Key *assertTypeInfo
  519. Custom string
  520. }
  521. func assertParseNonCompositeType(
  522. t *testing.T,
  523. def string,
  524. typeExpected assertTypeInfo,
  525. ) {
  526. result := parseType(def)
  527. if len(result.reversed) != 1 {
  528. t.Errorf("%s expected %d reversed values but there were %d", def, 1, len(result.reversed))
  529. }
  530. assertParseNonCompositeTypes(
  531. t,
  532. def,
  533. []assertTypeInfo{typeExpected},
  534. result.types,
  535. )
  536. // expect no composite part of the result
  537. if result.isComposite {
  538. t.Errorf("%s: Expected not composite", def)
  539. }
  540. if result.collections != nil {
  541. t.Errorf("%s: Expected nil collections: %v", def, result.collections)
  542. }
  543. }
  544. func assertParseCompositeType(
  545. t *testing.T,
  546. def string,
  547. typesExpected []assertTypeInfo,
  548. collectionsExpected map[string]assertTypeInfo,
  549. ) {
  550. result := parseType(def)
  551. if len(result.reversed) != len(typesExpected) {
  552. t.Errorf("%s expected %d reversed values but there were %d", def, len(typesExpected), len(result.reversed))
  553. }
  554. assertParseNonCompositeTypes(
  555. t,
  556. def,
  557. typesExpected,
  558. result.types,
  559. )
  560. // expect composite part of the result
  561. if !result.isComposite {
  562. t.Errorf("%s: Expected composite", def)
  563. }
  564. if result.collections == nil {
  565. t.Errorf("%s: Expected non-nil collections: %v", def, result.collections)
  566. }
  567. for name, typeExpected := range collectionsExpected {
  568. // check for an actual type for this name
  569. typeActual, found := result.collections[name]
  570. if !found {
  571. t.Errorf("%s.tcollections: Expected param named %s but there wasn't", def, name)
  572. } else {
  573. // remove the actual from the collection so we can detect extras
  574. delete(result.collections, name)
  575. // check the type
  576. assertParseNonCompositeTypes(
  577. t,
  578. def+"collections["+name+"]",
  579. []assertTypeInfo{typeExpected},
  580. []TypeInfo{typeActual},
  581. )
  582. }
  583. }
  584. if len(result.collections) != 0 {
  585. t.Errorf("%s.collections: Expected no more types in collections, but there was %v", def, result.collections)
  586. }
  587. }
  588. func assertParseNonCompositeTypes(
  589. t *testing.T,
  590. context string,
  591. typesExpected []assertTypeInfo,
  592. typesActual []TypeInfo,
  593. ) {
  594. if len(typesActual) != len(typesExpected) {
  595. t.Errorf("%s: Expected %d types, but there were %d", context, len(typesExpected), len(typesActual))
  596. }
  597. for i := range typesExpected {
  598. typeExpected := typesExpected[i]
  599. typeActual := typesActual[i]
  600. // shadow copy the context for local modification
  601. context := context
  602. if len(typesExpected) > 1 {
  603. context = context + "[" + strconv.Itoa(i) + "]"
  604. }
  605. // check the type
  606. if typeActual.Type != typeExpected.Type {
  607. t.Errorf("%s: Expected to parse Type to %s but was %s", context, typeExpected.Type, typeActual.Type)
  608. }
  609. // check the custom
  610. if typeActual.Custom != typeExpected.Custom {
  611. t.Errorf("%s: Expected to parse Custom %s but was %s", context, typeExpected.Custom, typeActual.Custom)
  612. }
  613. // check the elem
  614. if typeActual.Elem == nil && typeExpected.Elem != nil {
  615. t.Errorf("%s: Expected to parse Elem, but was nil ", context)
  616. } else if typeExpected.Elem == nil && typeActual.Elem != nil {
  617. t.Errorf("%s: Expected to not parse Elem, but was %+v", context, typeActual.Elem)
  618. } else if typeActual.Elem != nil && typeExpected.Elem != nil {
  619. assertParseNonCompositeTypes(
  620. t,
  621. context+".Elem",
  622. []assertTypeInfo{*typeExpected.Elem},
  623. []TypeInfo{*typeActual.Elem},
  624. )
  625. }
  626. // check the key
  627. if typeActual.Key == nil && typeExpected.Key != nil {
  628. t.Errorf("%s: Expected to parse Key, but was nil ", context)
  629. } else if typeExpected.Key == nil && typeActual.Key != nil {
  630. t.Errorf("%s: Expected to not parse Key, but was %+v", context, typeActual.Key)
  631. } else if typeActual.Key != nil && typeExpected.Key != nil {
  632. assertParseNonCompositeTypes(
  633. t,
  634. context+".Key",
  635. []assertTypeInfo{*typeExpected.Key},
  636. []TypeInfo{*typeActual.Key},
  637. )
  638. }
  639. }
  640. }