1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2002,2008 Oracle.  All rights reserved.
5 *
6 */
7
8/*
9 * Alexg 23-4-06
10 * Based on scr016 TestAppendRecno test application.
11 */
12
13package com.sleepycat.db.test;
14
15import org.junit.Before;
16import org.junit.After;
17import org.junit.AfterClass;
18import org.junit.BeforeClass;
19import org.junit.Test;
20import static org.junit.Assert.assertEquals;
21import static org.junit.Assert.fail;
22
23import java.io.File;
24import java.io.FileNotFoundException;
25import com.sleepycat.db.*;
26
27import com.sleepycat.db.DatabaseException;
28
29import com.sleepycat.db.test.TestUtils;
30
31public class AppendRecnoTest implements RecordNumberAppender {
32
33    public static final String RECNOTEST_DBNAME  =       "appendrecnotest.db";
34
35    public static final String[] EXPECTED_ENTRIES  =       { "data0_xyz", "data1_xy", "ata4_xyz", "ata5_xy",
36                                                                  "abc", "", "data9_xyz" };
37
38    int callback_count = 0;
39    boolean callback_throws = false;
40
41    @BeforeClass public static void ClassInit() {
42	    TestUtils.loadConfig(null);
43        TestUtils.check_file_removed(TestUtils.getDBFileName(RECNOTEST_DBNAME), true, true);
44    }
45
46    @AfterClass public static void ClassShutdown() {
47        TestUtils.check_file_removed(TestUtils.getDBFileName(RECNOTEST_DBNAME), true, true);
48    }
49
50    @Before public void PerTestInit()
51        throws Exception {
52	    TestUtils.removeall(true, false, TestUtils.BASETEST_DBDIR, TestUtils.getDBFileName(RECNOTEST_DBNAME));
53    }
54
55    @After public void PerTestShutdown()
56        throws Exception {
57    }
58
59    /*
60     * Test creating a new database.
61     */
62    @Test public void test1()
63        throws DatabaseException, FileNotFoundException
64    {
65        DatabaseConfig dbConfig = new DatabaseConfig();
66        dbConfig.setErrorStream(TestUtils.getErrorStream());
67        dbConfig.setErrorPrefix("AppendRecnoTest");
68        dbConfig.setType(DatabaseType.RECNO);
69        dbConfig.setPageSize(1024);
70        dbConfig.setAllowCreate(true);
71        dbConfig.setRecordNumberAppender(this);
72
73        Database db = new Database(TestUtils.getDBFileName(RECNOTEST_DBNAME), null, dbConfig);
74
75        for (int i=0; i<10; i++) {
76            TestUtils.DEBUGOUT("\n*** Iteration " + i );
77            boolean gotExcept = false;
78            try {
79                RecnoEntry key = new RecnoEntry(77+i);
80                DatabaseEntry data = new DatabaseEntry((new String("data" + i + "_xyz")).getBytes());
81                db.append(null, key, data);
82            }
83            catch (DatabaseException dbe) {
84                gotExcept = true;
85                // Can be expected since testing throwing from the appendRecordNumber callback.
86                TestUtils.DEBUGOUT("dbe: " + dbe);
87            } catch (ArrayIndexOutOfBoundsException e) {
88                gotExcept = true;
89                TestUtils.DEBUGOUT("ArrayIndex: " + e);
90            }
91            if((gotExcept && callback_throws == false ) || (!gotExcept && callback_throws == true))
92                TestUtils.DEBUGOUT(3, "appendRecordNumber callback exception or non-exception condition dealt with incorrectly. Case " + callback_count);
93        }
94
95        Cursor dbcp = db.openCursor(null, CursorConfig.DEFAULT);
96
97        // Walk through the table, validating the key/data pairs.
98        RecnoEntry readkey = new RecnoEntry();
99        DatabaseEntry readdata = new DatabaseEntry();
100    	TestUtils.DEBUGOUT("Dbc.get");
101
102    	int itemcount = 0;
103    	while (dbcp.getNext(readkey, readdata, LockMode.DEFAULT) == OperationStatus.SUCCESS) {
104    	    String gotString = new String(readdata.getData(), readdata.getOffset(), readdata.getSize());
105    	    TestUtils.DEBUGOUT(1, readkey.getRecno() + " : " + gotString);
106
107    	    if(readkey.getRecno() != ++itemcount)
108    	        TestUtils.DEBUGOUT(3, "Recno iteration out of order. key: " + readkey.getRecno() + " item: " + itemcount);
109
110    	    if(itemcount > EXPECTED_ENTRIES.length)
111    	        TestUtils.ERR("More entries in recno DB than expected.");
112
113
114    	    if(gotString.compareTo(EXPECTED_ENTRIES[itemcount-1]) != 0)
115    	        TestUtils.DEBUGOUT(3, "Recno - stored data mismatch. Expected: " + EXPECTED_ENTRIES[itemcount-1] + " received: " + gotString);
116    	}
117
118    	dbcp.close();
119    	db.close(false);
120
121    }
122
123    public void appendRecordNumber(Database db, DatabaseEntry data, int recno)
124        throws DatabaseException
125    {
126        callback_throws = false;
127        TestUtils.DEBUGOUT("AppendRecnoTest::appendRecordNumber. data " + new String(data.getData()) + " recno: " + recno);
128
129        switch (callback_count++) {
130            case 0:
131                // nothing
132                break;
133
134            case 1:
135                data.setSize(data.getSize() - 1);
136                break;
137
138            case 2:
139                // Should result in an error.
140                callback_throws = true;
141                TestUtils.DEBUGOUT("throwing...");
142                throw new DatabaseException("appendRecordNumber thrown");
143                //not reached
144
145            case 3:
146                // Should result in an error (size unchanged).
147                callback_throws = true;
148                data.setOffset(1);
149                break;
150
151            case 4:
152                data.setOffset(1);
153                data.setSize(data.getSize() - 1);
154                break;
155
156            case 5:
157                data.setOffset(1);
158                data.setSize(data.getSize() - 2);
159                break;
160
161            case 6:
162                data.setData(new String("abc").getBytes());
163                data.setSize(3);
164                break;
165
166            case 7:
167                // Should result in an error.
168                callback_throws = true;
169                data.setData(new String("abc").getBytes());
170                data.setSize(4);
171                break;
172// TODO: Broken - does not throw an exception.
173            case 8:
174                // TODO: Should this result in an error?
175                data.setData(null);
176                break;
177
178            default:
179                break;
180        }
181    }
182
183    static class RecnoEntry extends DatabaseEntry
184    {
185        public RecnoEntry() {
186            super();
187        }
188
189        public RecnoEntry(int value)
190        {
191            setReuseBuffer(false);
192            arr = new byte[4];
193            setData(arr);                // use our local array for data
194            setRecno(value);
195        }
196
197        public void setRecno(int value)
198        {
199            setRecordNumber(value);
200         }
201
202        public int getRecno()
203        {
204            return getRecordNumber();
205        }
206        byte arr[];
207    } // end of RecnoEntry sub-class.
208
209}
210