You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

199 lines
5.1 KiB

  1. package dynamodb_test
  2. import (
  3. "strconv"
  4. "github.com/goamz/goamz/dynamodb"
  5. . "gopkg.in/check.v1"
  6. )
  7. type StreamSuite struct {
  8. TableDescriptionT dynamodb.TableDescriptionT
  9. DynamoDBTest
  10. }
  11. func (s *StreamSuite) SetUpSuite(c *C) {
  12. setUpAuth(c)
  13. s.DynamoDBTest.TableDescriptionT = s.TableDescriptionT
  14. s.server = &dynamodb.Server{dynamodb_auth, dynamodb_region}
  15. pk, err := s.TableDescriptionT.BuildPrimaryKey()
  16. if err != nil {
  17. c.Skip(err.Error())
  18. }
  19. s.table = s.server.NewTable(s.TableDescriptionT.TableName, pk)
  20. // Cleanup
  21. s.TearDownSuite(c)
  22. _, err = s.server.CreateTable(s.TableDescriptionT)
  23. if err != nil {
  24. c.Fatal(err)
  25. }
  26. s.WaitUntilStatus(c, "ACTIVE")
  27. }
  28. var stream_suite_keys_only = &StreamSuite{
  29. TableDescriptionT: dynamodb.TableDescriptionT{
  30. TableName: "StreamTable",
  31. AttributeDefinitions: []dynamodb.AttributeDefinitionT{
  32. dynamodb.AttributeDefinitionT{"TestHashKey", "S"},
  33. dynamodb.AttributeDefinitionT{"TestRangeKey", "N"},
  34. },
  35. KeySchema: []dynamodb.KeySchemaT{
  36. dynamodb.KeySchemaT{"TestHashKey", "HASH"},
  37. dynamodb.KeySchemaT{"TestRangeKey", "RANGE"},
  38. },
  39. ProvisionedThroughput: dynamodb.ProvisionedThroughputT{
  40. ReadCapacityUnits: 1,
  41. WriteCapacityUnits: 1,
  42. },
  43. StreamSpecification: dynamodb.StreamSpecificationT{
  44. StreamEnabled: true,
  45. StreamViewType: "KEYS_ONLY",
  46. },
  47. },
  48. }
  49. var stream_suite_new_image = &StreamSuite{
  50. TableDescriptionT: dynamodb.TableDescriptionT{
  51. TableName: "StreamTable",
  52. AttributeDefinitions: []dynamodb.AttributeDefinitionT{
  53. dynamodb.AttributeDefinitionT{"TestHashKey", "S"},
  54. dynamodb.AttributeDefinitionT{"TestRangeKey", "N"},
  55. },
  56. KeySchema: []dynamodb.KeySchemaT{
  57. dynamodb.KeySchemaT{"TestHashKey", "HASH"},
  58. dynamodb.KeySchemaT{"TestRangeKey", "RANGE"},
  59. },
  60. ProvisionedThroughput: dynamodb.ProvisionedThroughputT{
  61. ReadCapacityUnits: 1,
  62. WriteCapacityUnits: 1,
  63. },
  64. StreamSpecification: dynamodb.StreamSpecificationT{
  65. StreamEnabled: true,
  66. StreamViewType: "NEW_IMAGE",
  67. },
  68. },
  69. }
  70. var _ = Suite(stream_suite_keys_only)
  71. var _ = Suite(stream_suite_new_image)
  72. func (s *StreamSuite) TestStream(c *C) {
  73. checkStream(s.table, c)
  74. }
  75. func checkStream(table *dynamodb.Table, c *C) {
  76. // list the table's streams
  77. streams, err := table.ListStreams("")
  78. if err != nil {
  79. c.Fatal(err)
  80. }
  81. c.Check(len(streams), Not(Equals), 0)
  82. c.Check(streams[0].TableName, Equals, table.Name)
  83. // stick a couple of items in the table
  84. attrs := []dynamodb.Attribute{
  85. *dynamodb.NewStringAttribute("TestAttr", "0"),
  86. }
  87. if ok, err := table.PutItem("0", "0", attrs); !ok {
  88. c.Fatal(err)
  89. }
  90. attrs = []dynamodb.Attribute{
  91. *dynamodb.NewStringAttribute("TestAttr", "1"),
  92. }
  93. if ok, err := table.PutItem("1", "1", attrs); !ok {
  94. c.Fatal(err)
  95. }
  96. // create a stream object
  97. stream := table.Server.NewStream(streams[0].StreamArn)
  98. // describe the steam
  99. desc, err := stream.DescribeStream("")
  100. if err != nil {
  101. c.Fatal(err)
  102. }
  103. tableDesc, err := table.DescribeTable()
  104. if err != nil {
  105. c.Fatal(err)
  106. }
  107. c.Check(desc.KeySchema[0], Equals, tableDesc.KeySchema[0])
  108. c.Check(desc.StreamArn, Equals, streams[0].StreamArn)
  109. c.Check(desc.StreamStatus, Equals, "ENABLED")
  110. c.Check(desc.StreamViewType, Equals, tableDesc.StreamSpecification.StreamViewType)
  111. c.Check(desc.TableName, Equals, table.Name)
  112. c.Check(len(desc.Shards), Equals, 1)
  113. // get a shard iterator
  114. shardIt, err := stream.GetShardIterator(desc.Shards[0].ShardId, "TRIM_HORIZON", "")
  115. if err != nil {
  116. c.Fatal(err)
  117. }
  118. c.Check(len(shardIt), Not(Equals), 0)
  119. // poll for records
  120. nextIt, records, err := stream.GetRecords(shardIt)
  121. if err != nil {
  122. c.Fatal(err)
  123. }
  124. c.Check(len(nextIt), Not(Equals), 0)
  125. c.Check(len(records), Equals, 2)
  126. for index, record := range records {
  127. c.Check(record.EventSource, Equals, "aws:dynamodb")
  128. c.Check(record.EventName, Equals, "INSERT")
  129. c.Check(len(record.EventID), Not(Equals), 0)
  130. // look at the actual record
  131. streamRec := record.StreamRecord
  132. c.Check(streamRec.StreamViewType, Equals, desc.StreamViewType)
  133. c.Check(len(streamRec.SequenceNumber), Not(Equals), 0)
  134. if streamRec.SizeBytes <= 0 {
  135. c.Errorf("Expected greater-than-zero size, got: %d", streamRec.SizeBytes)
  136. }
  137. // check the keys
  138. if streamRec.StreamViewType == "KEYS_ONLY" {
  139. checkKeys(streamRec.Keys, index, c)
  140. }
  141. // check the image
  142. if streamRec.StreamViewType == "NEW_IMAGE" {
  143. checkNewImage(streamRec.NewImage, index, c)
  144. }
  145. }
  146. }
  147. func checkKeys(keys map[string]*dynamodb.Attribute, expect int, c *C) {
  148. c.Check(len(keys), Equals, 2)
  149. value, err := strconv.Atoi(keys["TestHashKey"].Value)
  150. if err != nil {
  151. c.Fatal(err)
  152. }
  153. c.Check(value, Equals, expect)
  154. value, err = strconv.Atoi(keys["TestRangeKey"].Value)
  155. if err != nil {
  156. c.Fatal(err)
  157. }
  158. c.Check(value, Equals, expect)
  159. }
  160. func checkNewImage(image map[string]*dynamodb.Attribute, expect int, c *C) {
  161. c.Check(len(image), Equals, 3)
  162. value, err := strconv.Atoi(image["TestHashKey"].Value)
  163. if err != nil {
  164. c.Fatal(err)
  165. }
  166. c.Check(value, Equals, expect)
  167. value, err = strconv.Atoi(image["TestRangeKey"].Value)
  168. if err != nil {
  169. c.Fatal(err)
  170. }
  171. c.Check(value, Equals, expect)
  172. value, err = strconv.Atoi(image["TestAttr"].Value)
  173. if err != nil {
  174. c.Fatal(err)
  175. }
  176. c.Check(value, Equals, expect)
  177. }