logicalslotmanager_test.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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. _, err = lsm.Insert(util.PackLocation(10, 11))
  56. if sfe, ok := err.(*file.StorageFileError); !ok || sfe.Type != file.ErrAlreadyInUse {
  57. t.Error(err)
  58. return
  59. }
  60. sf.ReleaseInUse(record)
  61. // Test insertion error when allocating free slots
  62. record, err = fsf.Get(1)
  63. if err != nil {
  64. t.Error(err)
  65. return
  66. }
  67. _, err = lsm.Insert(util.PackLocation(10, 11))
  68. if sfe, ok := err.(*file.StorageFileError); !ok || sfe.Type != file.ErrAlreadyInUse {
  69. t.Error(err)
  70. return
  71. }
  72. fsf.ReleaseInUse(record)
  73. // Insert a locations
  74. loc, err := lsm.Insert(util.PackLocation(10, 11))
  75. if err != nil {
  76. t.Error(err)
  77. return
  78. }
  79. checkLocation(t, loc, 1, pageview.OffsetTransData)
  80. // Test error checking when force inserting a location (page does not exist)
  81. record, err = sf.Get(2)
  82. if err != nil {
  83. t.Error(err)
  84. return
  85. }
  86. err = lsm.ForceInsert(util.PackLocation(2, 2), util.PackLocation(12, 13))
  87. if sfe, ok := err.(*file.StorageFileError); !ok || sfe.Type != file.ErrAlreadyInUse {
  88. t.Error(err)
  89. return
  90. }
  91. sf.ReleaseInUse(record)
  92. // Force insert a location
  93. if err = lsm.ForceInsert(util.PackLocation(2, 2), util.PackLocation(12, 13)); err != nil {
  94. t.Error(err)
  95. return
  96. }
  97. // Test error checking when force inserting a location (this time the page exists)
  98. record, err = sf.Get(2)
  99. if err != nil {
  100. t.Error(err)
  101. return
  102. }
  103. err = lsm.ForceInsert(util.PackLocation(2, 2), util.PackLocation(12, 13))
  104. if sfe, ok := err.(*file.StorageFileError); !ok || sfe.Type != file.ErrAlreadyInUse {
  105. t.Error(err)
  106. return
  107. }
  108. sf.ReleaseInUse(record)
  109. testForceInsertPanic(t, lsm)
  110. // Check that the physical slot infos have been stored in the logical slots
  111. _testLogicalSlot(t, sf, 1, pageview.OffsetTransData, 10, 11)
  112. _testLogicalSlot(t, sf, 2, 2, 12, 13)
  113. // Free a slot
  114. record, err = sf.Get(2)
  115. if err != nil {
  116. t.Error(err)
  117. return
  118. }
  119. err = lsm.Free(util.PackLocation(2, 2))
  120. if sfe, ok := err.(*file.StorageFileError); !ok || sfe.Type != file.ErrAlreadyInUse {
  121. t.Error("Unexpected free result:", err)
  122. return
  123. }
  124. sf.ReleaseInUse(record)
  125. if err = lsm.Free(util.PackLocation(2, 2)); err != nil {
  126. t.Error(err)
  127. return
  128. }
  129. // Check error when fetching from the free manager (the free manager has
  130. // nothing stored but should fail since it can't look on page 1)
  131. record, err = fsf.Get(1)
  132. if err != nil {
  133. t.Error(err)
  134. return
  135. }
  136. _, err = lsm.Insert(util.PackLocation(12, 13))
  137. if sfe, ok := err.(*file.StorageFileError); !ok || sfe.Type != file.ErrAlreadyInUse {
  138. t.Error("Unexpected free result:", err)
  139. return
  140. }
  141. fsf.ReleaseInUse(record)
  142. // Check error when updating a logical slot
  143. record, err = sf.Get(1)
  144. if err != nil {
  145. t.Error(err)
  146. return
  147. }
  148. err = lsm.Update(util.PackLocation(1, 3), util.PackLocation(12, 13))
  149. if sfe, ok := err.(*file.StorageFileError); !ok || sfe.Type != file.ErrAlreadyInUse {
  150. t.Error("Unexpected update result:", err)
  151. return
  152. }
  153. sf.ReleaseInUse(record)
  154. if err := psf.Close(); err != nil {
  155. t.Error(err)
  156. return
  157. }
  158. if err := fpsf.Close(); err != nil {
  159. t.Error(err)
  160. return
  161. }
  162. }
  163. func testForceInsertPanic(t *testing.T, lsm *LogicalSlotManager) {
  164. defer func() {
  165. if r := recover(); r == nil {
  166. t.Error("Force inserting to an existing location did not cause a panic.")
  167. }
  168. }()
  169. lsm.ForceInsert(util.PackLocation(2, 2), util.PackLocation(12, 13))
  170. }
  171. func _testLogicalSlot(t *testing.T, sf *file.StorageFile,
  172. logicalRecord uint64, logicalOffset uint16,
  173. physicalRecord uint64, physicalOffset uint16) {
  174. record, err := sf.Get(logicalRecord)
  175. if err != nil {
  176. t.Error(err)
  177. return
  178. }
  179. slotinfo := record.ReadUInt64(int(logicalOffset))
  180. if slotinfo != util.PackLocation(physicalRecord, physicalOffset) {
  181. t.Error("Unexpected physical location was stored in logical slot:",
  182. logicalRecord, logicalOffset, " expected:", physicalRecord, physicalOffset,
  183. "got:", util.LocationRecord(slotinfo), util.LocationOffset(slotinfo))
  184. }
  185. sf.ReleaseInUse(record)
  186. }