55import java .io .IOException ;
66import java .io .InputStream ;
77
8+ import io .objectbox .exception .FileCorruptException ;
89import io .objectbox .exception .PagesCorruptException ;
910import io .objectbox .model .ValidateOnOpenMode ;
1011import org .greenrobot .essentials .io .IoUtils ;
1112import org .junit .Before ;
1213import org .junit .Test ;
1314
15+ import static org .junit .Assert .assertEquals ;
1416import static org .junit .Assert .assertNotNull ;
17+ import static org .junit .Assert .assertThrows ;
1518import static org .junit .Assert .assertTrue ;
1619import static org .junit .Assert .fail ;
1720
@@ -38,14 +41,7 @@ public void setUpBuilder() {
3841 public void validateOnOpen () {
3942 // Create a database first; we must create the model only once (ID/UID sequences would be different 2nd time)
4043 byte [] model = createTestModel (null );
41- builder = new BoxStoreBuilder (model ).directory (boxStoreDir );
42- builder .entity (new TestEntity_ ());
43- store = builder .build ();
44-
45- TestEntity object = new TestEntity (0 );
46- object .setSimpleString ("hello hello" );
47- long id = getTestEntityBox ().put (object );
48- store .close ();
44+ long id = buildNotCorruptedDatabase (model );
4945
5046 // Then re-open database with validation and ensure db is operational
5147 builder = new BoxStoreBuilder (model ).directory (boxStoreDir );
@@ -57,27 +53,26 @@ public void validateOnOpen() {
5753 }
5854
5955
60- @ Test ( expected = PagesCorruptException . class )
56+ @ Test
6157 public void validateOnOpenCorruptFile () throws IOException {
6258 File dir = prepareTempDir ("object-store-test-corrupted" );
63- File badDataFile = prepareBadDataFile (dir );
59+ prepareBadDataFile (dir , "corrupt-pageno-in-branch-data.mdb" );
6460
6561 builder = BoxStoreBuilder .createDebugWithoutModel ().directory (dir );
6662 builder .validateOnOpen (ValidateOnOpenMode .Full );
67- try {
68- store = builder .build ();
69- } finally {
70- boolean delOk = badDataFile .delete ();
71- delOk &= new File (dir , "lock.mdb" ).delete ();
72- delOk &= dir .delete ();
73- assertTrue (delOk ); // Try to delete all before asserting
74- }
63+
64+ @ SuppressWarnings ("resource" )
65+ FileCorruptException ex = assertThrows (PagesCorruptException .class , () -> builder .build ());
66+ assertEquals ("Validating pages failed (page not found)" , ex .getMessage ());
67+
68+ // Clean up
69+ deleteAllFiles (dir );
7570 }
7671
7772 @ Test
7873 public void usePreviousCommitWithCorruptFile () throws IOException {
7974 File dir = prepareTempDir ("object-store-test-corrupted" );
80- prepareBadDataFile (dir );
75+ prepareBadDataFile (dir , "corrupt-pageno-in-branch-data.mdb" );
8176 builder = BoxStoreBuilder .createDebugWithoutModel ().directory (dir );
8277 builder .validateOnOpen (ValidateOnOpenMode .Full ).usePreviousCommit ();
8378 store = builder .build ();
@@ -91,7 +86,7 @@ public void usePreviousCommitWithCorruptFile() throws IOException {
9186 @ Test
9287 public void usePreviousCommitAfterFileCorruptException () throws IOException {
9388 File dir = prepareTempDir ("object-store-test-corrupted" );
94- prepareBadDataFile (dir );
89+ prepareBadDataFile (dir , "corrupt-pageno-in-branch-data.mdb" );
9590 builder = BoxStoreBuilder .createDebugWithoutModel ().directory (dir );
9691 builder .validateOnOpen (ValidateOnOpenMode .Full );
9792 try {
@@ -109,15 +104,65 @@ public void usePreviousCommitAfterFileCorruptException() throws IOException {
109104 assertTrue (store .deleteAllFiles ());
110105 }
111106
112- private File prepareBadDataFile (File dir ) throws IOException {
107+ @ Test
108+ public void validateOnOpenKv () {
109+ // Create a database first; we must create the model only once (ID/UID sequences would be different 2nd time)
110+ byte [] model = createTestModel (null );
111+ long id = buildNotCorruptedDatabase (model );
112+
113+ // Then re-open database with validation and ensure db is operational
114+ builder = new BoxStoreBuilder (model ).directory (boxStoreDir );
115+ builder .entity (new TestEntity_ ());
116+ builder .validateOnOpenKv ();
117+ store = builder .build ();
118+ assertNotNull (getTestEntityBox ().get (id ));
119+ getTestEntityBox ().put (new TestEntity (0 ));
120+ }
121+
122+ @ Test
123+ public void validateOnOpenKvCorruptFile () throws IOException {
124+ File dir = prepareTempDir ("obx-store-validate-kv-corrupted" );
125+ prepareBadDataFile (dir , "corrupt-keysize0-data.mdb" );
126+
127+ builder = BoxStoreBuilder .createDebugWithoutModel ().directory (dir );
128+ builder .validateOnOpenKv ();
129+
130+ @ SuppressWarnings ("resource" )
131+ FileCorruptException ex = assertThrows (FileCorruptException .class , () -> builder .build ());
132+ assertEquals ("KV validation failed; key is empty (KV pair number: 1, key size: 0, data size: 112)" ,
133+ ex .getMessage ());
134+
135+ // Clean up
136+ deleteAllFiles (dir );
137+ }
138+
139+ /**
140+ * Returns the id of the inserted test entity.
141+ */
142+ private long buildNotCorruptedDatabase (byte [] model ) {
143+ builder = new BoxStoreBuilder (model ).directory (boxStoreDir );
144+ builder .entity (new TestEntity_ ());
145+ store = builder .build ();
146+
147+ TestEntity object = new TestEntity (0 );
148+ object .setSimpleString ("hello hello" );
149+ long id = getTestEntityBox ().put (object );
150+ store .close ();
151+ return id ;
152+ }
153+
154+ /**
155+ * Copies the given file from resources to the given directory as "data.mdb".
156+ */
157+ private void prepareBadDataFile (File dir , String resourceName ) throws IOException {
113158 assertTrue (dir .mkdir ());
114159 File badDataFile = new File (dir , "data.mdb" );
115- try (InputStream badIn = getClass ().getResourceAsStream ("corrupt-pageno-in-branch-data.mdb" )) {
160+ try (InputStream badIn = getClass ().getResourceAsStream (resourceName )) {
161+ assertNotNull (badIn );
116162 try (FileOutputStream badOut = new FileOutputStream (badDataFile )) {
117163 IoUtils .copyAllBytes (badIn , badOut );
118164 }
119165 }
120- return badDataFile ;
121166 }
122167
123168}
0 commit comments