View Javadoc
1   /*
2   Copyright (c) 2007 Health Market Science, Inc.
3   
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7   
8       http://www.apache.org/licenses/LICENSE-2.0
9   
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
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   * @author Tim McCune
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 }