001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026: package javax.microedition.rms;
027:
028: import com.sun.midp.i3test.*;
029:
030: import java.util.Random;
031:
032: public class TestRecordStore extends TestCase {
033: final String RECORD_STORE_NAME = "testrms";
034: byte[] smallData;
035: byte[] largeData;
036: int recordId1, recordId2;
037:
038: /**
039: * Add a small record then a large record.
040: */
041: private void setupRSTest() throws RecordStoreException {
042:
043: smallData = new byte[5]; // 5 Bytes
044: // Contents are 0,1,...,n
045: for (int i = 0; i < smallData.length; i++) {
046: smallData[i] = (byte) i;
047: }
048:
049: Random random = new Random();
050: largeData = new byte[10 * 1024]; // 10K Bytes
051: // Contents are 0,1,...,n
052: for (int i = 0; i < largeData.length; i++) {
053: largeData[i] = (byte) (random.nextInt(8) & 0xff);
054: }
055:
056: // Remove old record store
057: try {
058: RecordStore.deleteRecordStore(RECORD_STORE_NAME);
059: } catch (RecordStoreNotFoundException rnfe) {
060: }
061:
062: RecordStore store = RecordStore.openRecordStore(
063: RECORD_STORE_NAME, true);
064: recordId1 = store.addRecord(smallData, 0, smallData.length);
065: recordId2 = store.addRecord(largeData, 0, largeData.length);
066: store.closeRecordStore();
067: }
068:
069: private void testSequentialRMS() throws RecordStoreException {
070: RecordStore store1 = null;
071: RecordStore store2 = null;
072: boolean exceptionThrown = false;
073:
074: declare("Sequential access");
075:
076: store1 = RecordStore.openForLockTesting(RECORD_STORE_NAME);
077:
078: try {
079:
080: try {
081: store2 = RecordStore
082: .openForLockTesting(RECORD_STORE_NAME);
083: } catch (RecordStoreException re) {
084: exceptionThrown = true;
085: }
086:
087: if (store2 != null) {
088: store2.closeRecordStore();
089: }
090: } finally {
091: store1.closeRecordStore();
092: }
093:
094: assertTrue(exceptionThrown);
095: }
096:
097: private void testEnumeration() throws RecordStoreException {
098:
099: declare("getNumRecords");
100: RecordStore store = RecordStore.openRecordStore(
101: RECORD_STORE_NAME, false);
102: assertTrue(store.getNumRecords() == 2);
103:
104: declare("Enumeration nextRecordId");
105: RecordEnumeration recordenumeration = store.enumerateRecords(
106: null, null, true);
107: assertTrue("recordId1",
108: recordenumeration.nextRecordId() == recordId1);
109: assertTrue("recordId2",
110: recordenumeration.nextRecordId() == recordId2);
111:
112: declare("Enumeration nextRecord");
113: byte record[];
114: int i;
115:
116: recordenumeration.reset();
117:
118: record = recordenumeration.nextRecord();
119: for (i = 0; i < record.length; i++)
120: if (record[i] != smallData[i])
121: break;
122: assertTrue("small", record.length == smallData.length
123: && i == record.length);
124:
125: record = recordenumeration.nextRecord();
126: for (i = 0; i < record.length; i++)
127: if (record[i] != largeData[i])
128: break;
129:
130: assertTrue("large", record.length == largeData.length
131: && i == record.length);
132:
133: store.closeRecordStore();
134: }
135:
136: private void testCompactRecords() throws RecordStoreException {
137:
138: declare("testCompactRecords");
139: RecordStore store = RecordStore.openRecordStore(
140: RECORD_STORE_NAME, false);
141:
142: // Delete the small record
143: store.deleteRecord(recordId1);
144:
145: // Close the store to exercise compacting code
146: store.closeRecordStore();
147:
148: // Reopen and check for the large record
149: store = RecordStore.openRecordStore(RECORD_STORE_NAME, false);
150:
151: byte record[] = store.getRecord(recordId2);
152: int i;
153:
154: for (i = 0; i < record.length; i++)
155: if (record[i] != largeData[i])
156: break;
157:
158: assertTrue(record.length == largeData.length
159: && i == record.length);
160:
161: store.closeRecordStore();
162: }
163:
164: /**
165: * Creates a pseudo random record which is actually a fragment of
166: * largeData array.
167: * @param size of record required
168: * @return byte array of size requested
169: */
170: private byte[] getRandomRecord(int size) {
171: byte[] record = new byte[size];
172: byte ind = (byte) (new Random().nextInt(7) & 0x7f);
173:
174: record[0] = ind;
175: for (int i = 1; i < size; i++) {
176: record[i] = largeData[(ind + i) % largeData.length];
177: }
178:
179: return record;
180: }
181:
182: /**
183: * Checks if record given could be created by getRandomRecord().
184: * @param record record to be checked
185: * @return false if record with content given cannot be created by
186: * getRandomRecord()
187: */
188: private boolean isValidRandomRecord(byte[] record) {
189: if (record.length < 2) {
190: return false;
191: }
192:
193: byte ind = record[0];
194: if (ind < 0) {
195: return false;
196: }
197:
198: for (int i = 1; i < record.length; i++) {
199: if (record[i] != largeData[(ind + i) % largeData.length]) {
200: return false;
201: }
202: }
203:
204: return true;
205:
206: }
207:
208: private void testSizeLimit() throws RecordStoreException {
209: final int RECORD_SIZE = 64;
210: final int DOUBLE_SIZE = RECORD_SIZE * 2;
211: int id1 = -1;
212: int id2 = -1;
213:
214: declare("testSizeLimit");
215:
216: RecordStore store = RecordStore.openRecordStore(RECORD_STORE_NAME, true);
217:
218: try {
219: id1 = store.addRecord(getRandomRecord(RECORD_SIZE), 0, RECORD_SIZE);
220: while (true) {
221: id2 = store.addRecord(getRandomRecord(RECORD_SIZE),
222: 0, RECORD_SIZE);
223: }
224: } catch (RecordStoreFullException e) {
225: // Ok, the record store is full, now deleting two short records
226: assertTrue("failed adding two distinct records", id1 != id2);
227: store.deleteRecord(id1);
228: store.deleteRecord(id2);
229:
230: // Now there should be enough space for one double-size record
231: try {
232: store.addRecord(getRandomRecord(DOUBLE_SIZE), 0, DOUBLE_SIZE);
233:
234: //Checking data is not damaged by preceding operations
235: RecordEnumeration enum = store.enumerateRecords(null, null, false);
236: boolean damaged = false;
237:
238: while (enum.hasNextElement()) {
239: int id = enum.nextRecordId();
240: byte[] record = store.getRecord(id);
241: if (id == id1 || id == id2 || !isValidRandomRecord(record)) {
242: damaged = true;
243: break;
244: }
245: }
246:
247: assertTrue("data is damaged", !damaged);
248:
249: } catch (Throwable t) {
250: fail("Failed adding a record to freed space: " + t);
251: }
252: }
253:
254: store.closeRecordStore();
255: }
256:
257: private void cleanup() throws RecordStoreException {
258: RecordStore.deleteRecordStore(RECORD_STORE_NAME);
259: }
260:
261: public void runTests() throws Throwable {
262:
263: setupRSTest();
264:
265: try {
266: testSequentialRMS();
267: testEnumeration();
268: testCompactRecords();
269: cleanup();
270: testSizeLimit();
271: } catch (Throwable t) {
272: t.printStackTrace();
273: } finally {
274: cleanup();
275: }
276:
277: }
278: }
|