001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.flatfile;
018
019import static org.junit.Assert.assertArrayEquals;
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertTrue;
022import static org.junit.Assert.fail;
023
024import java.io.ByteArrayInputStream;
025import java.io.IOException;
026import java.util.Arrays;
027
028import org.apache.commons.flatfile.FieldSupport.Overflow;
029import org.apache.commons.flatfile.FieldSupport.Underflow;
030import org.junit.Test;
031
032/**
033 * Test dynamic fields.
034 */
035public class DynamicFieldTest extends EntityParserTestBase {
036    private static final int BUFFER_SIZE = 20;
037
038    private static final byte[] SMALL_BYTES = new byte[0];
039    private static final byte[] LARGE_BYTES = new byte[1024];
040
041    static {
042        Arrays.fill(LARGE_BYTES, (byte) 'a');
043    }
044
045    @Test
046    public void test1() throws Exception {
047        DynamicField df = get("df1");
048        assertEquals(0, df.length());
049        assertBounds(df, 0, 1);
050        assertLoad(df);
051    }
052
053    @Test
054    public void test2() throws Exception {
055        DynamicField df = get("df2");
056        assertEquals(0, df.length());
057        assertBounds(df, DynamicField.Bounds.DEFAULT.getMinimum(), 1);
058        assertLoad(df);
059    }
060
061    @Test
062    public void test3() throws Exception {
063        DynamicField df = get("df3");
064        assertEquals(0, df.length());
065        assertBounds(df, 0, DynamicField.Bounds.DEFAULT.getMaximum());
066        assertLoad(df);
067    }
068
069    @Test
070    public void test4() throws Exception {
071        DynamicField df = get("df4");
072        assertEquals(0, df.length());
073        assertBounds(df, DynamicField.Bounds.DEFAULT);
074        assertLoad(df);
075    }
076
077    @Test
078    public void test5() throws Exception {
079        DynamicField df = get("df5");
080        assertEquals(3, df.length());
081        byte[] foo = "foo".getBytes();
082        assertArrayEquals(foo, df.getValue());
083        assertBounds(df, DynamicField.Bounds.DEFAULT);
084        assertLoad(df);
085    }
086
087    @Test
088    public void test6() throws Exception {
089        DynamicField df = get("df6");
090        assertEquals(0, df.length());
091        assertBounds(df, 0, 0);
092        assertLoad(df);
093    }
094
095    @Test
096    public void test7() throws Exception {
097        DynamicField df = get("df7");
098        assertEquals(0, df.length());
099        assertBounds(df, DynamicField.Bounds.DEFAULT.getMinimum(), 0);
100        assertLoad(df);
101    }
102
103    @Test
104    public void test8() throws Exception {
105        DynamicField df = get("df8");
106        assertBounds(df, 1, 1);
107        assertArrayEquals(new byte[] { ' ' }, df.getValue());
108        assertLoad(df);
109    }
110
111    @Test
112    public void test9() throws Exception {
113        DynamicField df = get("df9");
114        assertBounds(df, 1, 3);
115        assertArrayEquals(" ".getBytes(), df.getValue());
116        assertLoad(df);
117    }
118
119    @Test
120    public void testUnboundedArray() throws Exception {
121        EntityArray a = (EntityArray) entityFactory.getEntity("unboundedArray");
122        assertEquals(0, a.length());
123        a.getChild(1).setValue("foo".getBytes());
124        assertArrayEquals("foo".getBytes(), a.getValue());
125    }
126
127    @Test
128    public void testUnboundedDelimitedArray() throws Exception {
129        EntityArray a = (EntityArray) entityFactory
130                .getEntity("unboundedDelimitedArray");
131        assertArrayEquals("---".getBytes(), a.getValue());
132        a.getChild(1).setValue("foo".getBytes());
133        assertArrayEquals("-foo--".getBytes(), a.getValue());
134    }
135
136    @Test
137    public void testBoundedArray() throws Exception {
138        EntityArray a = (EntityArray) entityFactory.getEntity("boundedArray");
139        assertArrayEquals("   ".getBytes(), a.getValue());
140        a.getChild(1).setValue("foo".getBytes());
141        assertArrayEquals(" foo ".getBytes(), a.getValue());
142    }
143
144    @Test
145    public void testBoundedDelimitedArray() throws Exception {
146        EntityArray a = (EntityArray) entityFactory
147                .getEntity("boundedDelimitedArray");
148        assertArrayEquals(" \n \n \n".getBytes(), a.getValue());
149        a.getChild(1).setValue("foo".getBytes());
150        assertArrayEquals(" \nfoo\n \n".getBytes(), a.getValue());
151
152    }
153
154    @Test
155    public void testNestedUncertainty() throws Exception {
156        EntityArray a = (EntityArray) entityFactory
157                .getEntity("nestedUncertainty");
158        assertTrue(a.isSizable());
159        a.setSize(10);
160        assertArrayEquals(SMALL_BYTES, a.getValue());
161        StringBuffer buf = new StringBuffer();
162        for (int i = 0; i < 10; i++) {
163            byte[] b = new byte[i + 1];
164            Arrays.fill(b, (byte) ((int) 'a' + i));
165            buf.append(new String(b));
166            a.getChild(i).setValue(b);
167        }
168        assertArrayEquals(buf.toString().getBytes(), a.getValue());
169    }
170
171    private void assertBounds(DynamicField df, int min, int max) {
172        assertBounds(df, new DynamicField.Bounds(min, max));
173    }
174
175    private void assertBounds(DynamicField df, DynamicField.Bounds bounds) {
176        assertEquals(bounds, df.getBounds());
177        testValue(df, SMALL_BYTES);
178        testValue(df, LARGE_BYTES);
179    }
180
181    private void assertLoad(DynamicField df) throws IOException {
182        df.readFrom(new ByteArrayInputStream(LARGE_BYTES));
183        int max = df.getBounds().getMaximum();
184        int expectedLength = Math.min(max, LARGE_BYTES.length);
185        assertEquals(expectedLength, df.length());
186        byte[] expec;
187        if (LARGE_BYTES.length < max) {
188            expec = LARGE_BYTES;
189        } else {
190            expec = new byte[max];
191            System.arraycopy(LARGE_BYTES, 0, expec, 0, expec.length);
192        }
193        assertArrayEquals(expec, df.getValue());
194    }
195
196    private void testValue(DynamicField df, byte[] value) {
197        int len = value.length;
198        int min = df.getBounds().getMinimum();
199        int max = df.getBounds().getMaximum();
200        if (df.getUnderflow() == Underflow.ERROR && len < min
201                || df.getOverflow() == Overflow.ERROR && len > max) {
202            byte[] old = df.getValue();
203            try {
204                df.setValue(value);
205                fail(new String(value));
206            } catch (IllegalArgumentException e) {
207                assertArrayEquals(old, df.getValue());
208            }
209        } else {
210            df.setValue(value);
211            assertTrue(len < min || len > max
212                    || Arrays.equals(value, df.getValue()));
213        }
214    }
215
216    private DynamicField get(String name) {
217        return (DynamicField) entityFactory.getEntity(name);
218    }
219
220    protected String getSource() {
221        return "dynamicField.test";
222    }
223
224}