1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.healthmarketscience.jackcess;
18
19 import java.io.IOException;
20 import java.nio.ByteBuffer;
21 import java.nio.charset.Charset;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.List;
25 import java.util.TimeZone;
26
27 import com.healthmarketscience.jackcess.impl.ColumnImpl;
28 import com.healthmarketscience.jackcess.impl.JetFormat;
29 import com.healthmarketscience.jackcess.impl.PageChannel;
30 import com.healthmarketscience.jackcess.impl.TableImpl;
31 import junit.framework.TestCase;
32
33
34
35
36 public class TableTest extends TestCase {
37
38 private final PageChannel _pageChannel = new PageChannel(true) {};
39 private List<ColumnImpl> _columns = new ArrayList<ColumnImpl>();
40 private TestTable _testTable;
41 private int _varLenIdx;
42 private int _fixedOffset;
43
44
45 public TableTest(String name) {
46 super(name);
47 }
48
49 private void reset() {
50 _testTable = null;
51 _columns = new ArrayList<ColumnImpl>();
52 _varLenIdx = 0;
53 _fixedOffset = 0;
54 }
55
56 public void testCreateRow() throws Exception {
57 reset();
58 newTestColumn(DataType.INT, false);
59 newTestColumn(DataType.TEXT, false);
60 newTestColumn(DataType.TEXT, false);
61 newTestTable();
62
63 int colCount = _columns.size();
64 ByteBuffer buffer = createRow(9, "Tim", "McCune");
65
66 assertEquals((short) colCount, buffer.getShort());
67 assertEquals((short) 9, buffer.getShort());
68 assertEquals((byte) 'T', buffer.get());
69 assertEquals((short) 22, buffer.getShort(22));
70 assertEquals((short) 10, buffer.getShort(24));
71 assertEquals((short) 4, buffer.getShort(26));
72 assertEquals((short) 2, buffer.getShort(28));
73 assertEquals((byte) 7, buffer.get(30));
74 }
75
76 public void testUnicodeCompression() throws Exception {
77 reset();
78 newTestColumn(DataType.TEXT, false);
79 newTestColumn(DataType.TEXT, false);
80 newTestTable();
81
82 String small = "this is a string";
83 String smallNotAscii = "this is a string\0";
84 String large = TestUtil.createString(30);
85 String largeNotAscii = large + "\0";
86
87 ByteBuffer[] buf1 = encodeColumns(small, large);
88 ByteBuffer[] buf2 = encodeColumns(smallNotAscii, largeNotAscii);
89
90 reset();
91 newTestColumn(DataType.TEXT, true);
92 newTestColumn(DataType.TEXT, true);
93 newTestTable();
94
95 ByteBuffer[] bufCmp1 = encodeColumns(small, large);
96 ByteBuffer[] bufCmp2 = encodeColumns(smallNotAscii, largeNotAscii);
97
98 assertEquals(buf1[0].remaining(),
99 (bufCmp1[0].remaining() + small.length() - 2));
100 assertEquals(buf1[1].remaining(),
101 (bufCmp1[1].remaining() + large.length() - 2));
102
103 for(int i = 0; i < buf2.length; ++i) {
104 assertTrue(Arrays.equals(toBytes(buf2[i]), toBytes(bufCmp2[i])));
105 }
106
107 assertEquals(Arrays.asList(small, large),
108 Arrays.asList(decodeColumns(bufCmp1)));
109 assertEquals(Arrays.asList(smallNotAscii, largeNotAscii),
110 Arrays.asList(decodeColumns(bufCmp2)));
111
112 }
113
114 private ByteBuffer createRow(Object... row)
115 throws IOException
116 {
117 return _testTable.createRow(row);
118 }
119
120 private ByteBuffer[] encodeColumns(Object... row)
121 throws IOException
122 {
123 ByteBuffer[] result = new ByteBuffer[_columns.size()];
124 for(int i = 0; i < _columns.size(); ++i) {
125 ColumnImpl col = _columns.get(i);
126 result[i] = col.write(row[i], _testTable.getFormat().MAX_ROW_SIZE);
127 }
128 return result;
129 }
130
131 private Object[] decodeColumns(ByteBuffer[] buffers)
132 throws IOException
133 {
134 Object[] result = new Object[_columns.size()];
135 for(int i = 0; i < _columns.size(); ++i) {
136 ColumnImpl col = _columns.get(i);
137 result[i] = col.read(toBytes(buffers[i]));
138 }
139 return result;
140 }
141
142 private static byte[] toBytes(ByteBuffer buffer) {
143 buffer.rewind();
144 byte[] b = new byte[buffer.remaining()];
145 buffer.get(b);
146 return b;
147 }
148
149 private TableImpl newTestTable()
150 throws Exception
151 {
152 _testTable = new TestTable();
153 return _testTable;
154 }
155
156 private void newTestColumn(DataType type, final boolean compressedUnicode) {
157
158 int nextColIdx = _columns.size();
159 int nextVarLenIdx = 0;
160 int nextFixedOff = 0;
161
162 if(type.isVariableLength()) {
163 nextVarLenIdx = _varLenIdx++;
164 } else {
165 nextFixedOff = _fixedOffset;
166 _fixedOffset += type.getFixedSize();
167 }
168
169 ColumnImpl col = new ColumnImpl(null, null, type, nextColIdx, nextFixedOff,
170 nextVarLenIdx) {
171 @Override
172 public TableImpl getTable() {
173 return _testTable;
174 }
175 @Override
176 public JetFormat getFormat() {
177 return getTable().getFormat();
178 }
179 @Override
180 public PageChannel getPageChannel() {
181 return getTable().getPageChannel();
182 }
183 @Override
184 protected Charset getCharset() {
185 return getFormat().CHARSET;
186 }
187 @Override
188 public TimeZone getTimeZone() {
189 return TimeZone.getDefault();
190 }
191 @Override
192 public boolean isCompressedUnicode() {
193 return compressedUnicode;
194 }
195 };
196
197 _columns.add(col);
198 }
199
200 private class TestTable extends TableImpl {
201 private TestTable() throws IOException {
202 super(true, _columns);
203 }
204 public ByteBuffer createRow(Object... row) throws IOException {
205 return super.createRow(row, getPageChannel().createPageBuffer());
206 }
207 @Override
208 public PageChannel getPageChannel() {
209 return _pageChannel;
210 }
211 @Override
212 public JetFormat getFormat() {
213 return JetFormat.VERSION_4;
214 }
215 }
216 }