record_test.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /*
  2. * EliasDB
  3. *
  4. * Copyright 2016 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the Mozilla Public
  7. * License, v. 2.0. If a copy of the MPL was not distributed with this
  8. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. */
  10. package file
  11. import (
  12. "bytes"
  13. "fmt"
  14. "io"
  15. "reflect"
  16. "testing"
  17. "devt.de/krotik/common/bitutil"
  18. "devt.de/krotik/common/testutil"
  19. )
  20. func TestRecordInitialisation(t *testing.T) {
  21. r := new(Record)
  22. out := r.String()
  23. if out != "Record: 0 (dirty:false transCount:0 len:0 cap:0)\n"+
  24. "====\n"+
  25. "000000 \n"+
  26. "====\n" {
  27. t.Error("Unexpected output of empty record:", out)
  28. }
  29. rdata := []byte("This is a test")
  30. r = NewRecord(123, rdata)
  31. id := r.ID()
  32. if id != 123 {
  33. t.Error("Unexpected id:", id)
  34. }
  35. data := r.Data()
  36. if !bitutil.CompareByteArray(data, rdata) {
  37. t.Error("Unexpected initial data", data)
  38. }
  39. if r.Dirty() {
  40. t.Error("Record shouldn't be dirty right after it was created.")
  41. }
  42. // Test page view object storage
  43. dummyString := "TEST"
  44. r.SetPageView(dummyString)
  45. if r.PageView() != dummyString {
  46. t.Error("Unexpected page view object")
  47. }
  48. }
  49. func TestTransactionCounter(t *testing.T) {
  50. r := NewRecord(123, make([]byte, 20))
  51. if r.InTransaction() {
  52. t.Error("A fresh record should not be in a transaction.")
  53. }
  54. r.IncTransCount()
  55. if !r.InTransaction() {
  56. t.Error("Record should be in transaction after the transaction count was increased.")
  57. }
  58. if r.SetID(567) == nil {
  59. t.Error("It should not be possible to change the record id while in a transaction.")
  60. }
  61. r.DecTransCount()
  62. if r.SetID(789); r.ID() != 789 {
  63. t.Error("It should be possible to change the record id outside of a transaction.")
  64. }
  65. if r.InTransaction() {
  66. t.Error("Record should not be in transaction after the transaction count was decreased again.")
  67. }
  68. testTransactionCountPanic(t, r)
  69. }
  70. func testTransactionCountPanic(t *testing.T, r *Record) {
  71. defer func() {
  72. if r := recover(); r == nil {
  73. t.Error("Decreasing of transaction count did not cause a panic.")
  74. }
  75. }()
  76. r.DecTransCount()
  77. }
  78. func TestReadAndWrite(t *testing.T) {
  79. r := NewRecord(123, make([]byte, 20))
  80. r.WriteSingleByte(3, 0x42)
  81. if r.data[3] != 0x42 {
  82. t.Error("Unexpected value in read/write test", r.data[3], "expected: 0x42")
  83. }
  84. if !r.Dirty() {
  85. t.Error("Record should be marked as dirty after write operation.")
  86. }
  87. r.ClearDirty()
  88. if r.Dirty() {
  89. t.Error("Record should not be marked as dirty after clearing flag.")
  90. }
  91. r.WriteSingleByte(0, 0xff)
  92. showRWTestResult(t, r.ReadSingleByte(0) == byte(0xff), "a byte")
  93. r.WriteSingleByte(0, 0x01)
  94. showRWTestResult(t, r.ReadSingleByte(0) == byte(0x01), "a byte")
  95. r.WriteUInt16(0, 0x1234)
  96. showRWTestResult(t, r.ReadUInt16(0) == uint16(0x1234), "an uint16")
  97. r.WriteUInt16(0, 0xFFFF)
  98. showRWTestResult(t, r.ReadUInt16(0) == uint16(0xFFFF), "an uint16")
  99. r.WriteInt16(0, -0x1234)
  100. showRWTestResult(t, r.ReadInt16(0) == int16(-0x1234), "an int16")
  101. r.WriteInt16(0, -0x7FFF)
  102. showRWTestResult(t, r.ReadInt16(0) == int16(-0x7FFF), "an int16")
  103. r.WriteInt16(0, 0x7FFF)
  104. showRWTestResult(t, r.ReadInt16(0) == int16(0x7FFF), "an int16")
  105. r.WriteUInt32(0, 0x12345678)
  106. showRWTestResult(t, r.ReadUInt32(0) == uint32(0x12345678), "an uint32")
  107. r.WriteUInt32(0, 0xFFFFFFFF)
  108. showRWTestResult(t, r.ReadUInt32(0) == uint32(0xFFFFFFFF), "an uint32")
  109. r.WriteInt32(0, -0x12345678)
  110. showRWTestResult(t, r.ReadInt32(0) == int32(-0x12345678), "an int32")
  111. r.WriteInt32(0, -0x7FFFFFFF)
  112. showRWTestResult(t, r.ReadInt32(0) == int32(-0x7FFFFFFF), "an int32")
  113. r.WriteInt32(0, 0x7FFFFFFF)
  114. showRWTestResult(t, r.ReadInt32(0) == int32(0x7FFFFFFF), "an int32")
  115. r.WriteUInt64(0, 0x1234567891234567)
  116. showRWTestResult(t, r.ReadUInt64(0) == uint64(0x1234567891234567), "an uint64")
  117. r.WriteUInt64(0, 0xFFFFFFFFFFFFFFFF)
  118. showRWTestResult(t, r.ReadUInt64(0) == uint64(0xFFFFFFFFFFFFFFFF), "an uint64")
  119. r.ClearData()
  120. if r.ReadUInt64(0) != 0 || r.Dirty() {
  121. t.Error("Record should be clean and not marked as dirty after it was cleaned.")
  122. }
  123. }
  124. func showRWTestResult(t *testing.T, res bool, operation string) {
  125. if !res {
  126. t.Error("Unexpected result while reading/writing", operation)
  127. }
  128. }
  129. func TestMarshalBinary(t *testing.T) {
  130. r := NewRecord(123, make([]byte, 20))
  131. r.WriteSingleByte(0, 0x41)
  132. r.WriteSingleByte(3, 0x42)
  133. r.WriteSingleByte(19, 0x43)
  134. r.transCount = 19
  135. data, _ := r.MarshalBinary()
  136. r2 := NewRecord(0, make([]byte, 20))
  137. err := r2.UnmarshalBinary(data)
  138. if err != nil {
  139. t.Error(err)
  140. return
  141. }
  142. if !reflect.DeepEqual(r, r2) {
  143. t.Error("Unmarshaled record should be the same as the original record")
  144. }
  145. ior := new(bytes.Buffer)
  146. ior.Write(data)
  147. r3, err := ReadRecord(ior)
  148. if err != nil {
  149. t.Error(err)
  150. return
  151. }
  152. if !reflect.DeepEqual(r, r3) {
  153. t.Error("Unmarshaled record should be the same as the original record")
  154. }
  155. ior = new(bytes.Buffer)
  156. ior.Write(data[1:5])
  157. _, err = ReadRecord(ior)
  158. if err == nil {
  159. t.Error("ReadRecord should return an error when given invalid data")
  160. return
  161. }
  162. data2, _ := r2.MarshalBinary()
  163. if !reflect.DeepEqual(data, data2) {
  164. t.Error("Marshaled representation of records should be the same")
  165. }
  166. // Test errors of writing
  167. for i := 0; i < len(data); i++ {
  168. buf := &testutil.ErrorTestingBuffer{RemainingSize: i, WrittenSize: 0}
  169. err := r.WriteRecord(buf)
  170. if _, ok := err.(testutil.ErrorTestingBuffer); !ok {
  171. t.Error("Unexpected error return:", err)
  172. }
  173. }
  174. r.ClearDirty()
  175. data, _ = r.MarshalBinary()
  176. buf := &testutil.ErrorTestingBuffer{RemainingSize: 8, WrittenSize: 0}
  177. err = r.WriteRecord(buf)
  178. if _, ok := err.(testutil.ErrorTestingBuffer); !ok {
  179. t.Error("Unexpected error return:", err)
  180. }
  181. for i := 0; i < len(data); i++ {
  182. err := r.UnmarshalBinary(data[0:i])
  183. if err != io.EOF && err != io.ErrUnexpectedEOF {
  184. fmt.Println("fail")
  185. t.Error("Unexpected error return:", err)
  186. }
  187. }
  188. }