logicalslotmanager_test.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  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 slotting
  11. import (
  12. "testing"
  13. "devt.de/krotik/eliasdb/storage/file"
  14. "devt.de/krotik/eliasdb/storage/paging"
  15. "devt.de/krotik/eliasdb/storage/slotting/pageview"
  16. "devt.de/krotik/eliasdb/storage/util"
  17. )
  18. func TestLogicalSlotManager(t *testing.T) {
  19. sf, err := file.NewDefaultStorageFile(DBDIR+"/test8_data", false)
  20. if err != nil {
  21. t.Error(err.Error())
  22. return
  23. }
  24. psf, err := paging.NewPagedStorageFile(sf)
  25. if err != nil {
  26. t.Error(err)
  27. return
  28. }
  29. fsf, err := file.NewDefaultStorageFile(DBDIR+"/test8_free", false)
  30. if err != nil {
  31. t.Error(err.Error())
  32. return
  33. }
  34. fpsf, err := paging.NewPagedStorageFile(fsf)
  35. if err != nil {
  36. t.Error(err)
  37. return
  38. }
  39. lsm := NewLogicalSlotManager(psf, fpsf)
  40. if lsm.ElementsPerPage() != 509 {
  41. t.Error("Unexpected elements per page:", lsm.ElementsPerPage())
  42. return
  43. }
  44. // Check return value when fetching from a logical slot which doesn't yet exist
  45. slotinfo, err := lsm.Fetch(util.PackLocation(1, pageview.OffsetTransData))
  46. if slotinfo != 0 || err != nil {
  47. t.Error("Unexpected fetch result:", slotinfo, err)
  48. }
  49. // Test insertion error
  50. record, err := sf.Get(1)
  51. if err != nil {
  52. t.Error(err)
  53. return
  54. }
  55. if _, err := lsm.Insert(util.PackLocation(10, 11)); err != file.ErrAlreadyInUse {
  56. t.Error(err)
  57. return
  58. }
  59. sf.ReleaseInUse(record)
  60. // Test insertion error when allocating free slots
  61. record, err = fsf.Get(1)
  62. if err != nil {
  63. t.Error(err)
  64. return
  65. }
  66. if _, err := lsm.Insert(util.PackLocation(10, 11)); err != file.ErrAlreadyInUse {
  67. t.Error(err)
  68. return
  69. }
  70. fsf.ReleaseInUse(record)
  71. // Insert a locations
  72. loc, err := lsm.Insert(util.PackLocation(10, 11))
  73. if err != nil {
  74. t.Error(err)
  75. return
  76. }
  77. checkLocation(t, loc, 1, pageview.OffsetTransData)
  78. // Test error checking when force inserting a location (page does not exist)
  79. record, err = sf.Get(2)
  80. if err != nil {
  81. t.Error(err)
  82. return
  83. }
  84. if err = lsm.ForceInsert(util.PackLocation(2, 2), util.PackLocation(12, 13)); err != file.ErrAlreadyInUse {
  85. t.Error(err)
  86. return
  87. }
  88. sf.ReleaseInUse(record)
  89. // Force insert a location
  90. if err = lsm.ForceInsert(util.PackLocation(2, 2), util.PackLocation(12, 13)); err != nil {
  91. t.Error(err)
  92. return
  93. }
  94. // Test error checking when force inserting a location (this time the page exists)
  95. record, err = sf.Get(2)
  96. if err != nil {
  97. t.Error(err)
  98. return
  99. }
  100. if err = lsm.ForceInsert(util.PackLocation(2, 2), util.PackLocation(12, 13)); err != file.ErrAlreadyInUse {
  101. t.Error(err)
  102. return
  103. }
  104. sf.ReleaseInUse(record)
  105. testForceInsertPanic(t, lsm)
  106. // Check that the physical slot infos have been stored in the logical slots
  107. _testLogicalSlot(t, sf, 1, pageview.OffsetTransData, 10, 11)
  108. _testLogicalSlot(t, sf, 2, 2, 12, 13)
  109. // Free a slot
  110. record, err = sf.Get(2)
  111. if err != nil {
  112. t.Error(err)
  113. return
  114. }
  115. if err = lsm.Free(util.PackLocation(2, 2)); err != file.ErrAlreadyInUse {
  116. t.Error("Unexpected free result:", err)
  117. return
  118. }
  119. sf.ReleaseInUse(record)
  120. if err = lsm.Free(util.PackLocation(2, 2)); err != nil {
  121. t.Error(err)
  122. return
  123. }
  124. // Check error when fetching from the free manager (the free manager has
  125. // nothing stored but should fail since it can't look on page 1)
  126. record, err = fsf.Get(1)
  127. if err != nil {
  128. t.Error(err)
  129. return
  130. }
  131. if _, err = lsm.Insert(util.PackLocation(12, 13)); err != file.ErrAlreadyInUse {
  132. t.Error("Unexpected free result:", err)
  133. return
  134. }
  135. fsf.ReleaseInUse(record)
  136. // Check error when updating a logical slot
  137. record, err = sf.Get(1)
  138. if err != nil {
  139. t.Error(err)
  140. return
  141. }
  142. if err = lsm.Update(util.PackLocation(1, 3), util.PackLocation(12, 13)); err != file.ErrAlreadyInUse {
  143. t.Error("Unexpected update result:", err)
  144. return
  145. }
  146. sf.ReleaseInUse(record)
  147. if err := psf.Close(); err != nil {
  148. t.Error(err)
  149. return
  150. }
  151. if err := fpsf.Close(); err != nil {
  152. t.Error(err)
  153. return
  154. }
  155. }
  156. func testForceInsertPanic(t *testing.T, lsm *LogicalSlotManager) {
  157. defer func() {
  158. if r := recover(); r == nil {
  159. t.Error("Force inserting to an existing location did not cause a panic.")
  160. }
  161. }()
  162. lsm.ForceInsert(util.PackLocation(2, 2), util.PackLocation(12, 13))
  163. }
  164. func _testLogicalSlot(t *testing.T, sf *file.StorageFile,
  165. logicalRecord uint64, logicalOffset uint16,
  166. physicalRecord uint64, physicalOffset uint16) {
  167. record, err := sf.Get(logicalRecord)
  168. if err != nil {
  169. t.Error(err)
  170. return
  171. }
  172. slotinfo := record.ReadUInt64(int(logicalOffset))
  173. if slotinfo != util.PackLocation(physicalRecord, physicalOffset) {
  174. t.Error("Unexpected physical location was stored in logical slot:",
  175. logicalRecord, logicalOffset, " expected:", physicalRecord, physicalOffset,
  176. "got:", util.LocationRecord(slotinfo), util.LocationOffset(slotinfo))
  177. }
  178. sf.ReleaseInUse(record)
  179. }