1 /*
2    Copyright 2010 Sun Microsystems, Inc.
3    All rights reserved. Use is subject to license terms.
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License, version 2.0,
7    as published by the Free Software Foundation.
8 
9    This program is also distributed with certain software (including
10    but not limited to OpenSSL) that is licensed under separate terms,
11    as designated in a particular file or component or in included license
12    documentation.  The authors of MySQL hereby grant you an additional
13    permission to link the program and your derivative works with the
14    separately licensed software that they have included with MySQL.
15 
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License, version 2.0, for more details.
20 
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
24 */
25 
26 package testsuite.clusterj;
27 
28 import java.io.IOException;
29 import java.io.InputStream;
30 
31 import java.util.ArrayList;
32 import java.util.List;
33 
34 import testsuite.clusterj.model.BlobTypes;
35 
36 public class BlobTest extends AbstractClusterJModelTest {
37 
38     /** The size of the blob column is 2 raised to the power i. */
39     private static final int NUMBER_TO_INSERT = 16;
40 
41     /** The blob instances for testing. */
42     protected List<BlobTypes> blobs = new ArrayList<BlobTypes>();
43 
44     @Override
localSetUp()45     public void localSetUp() {
46         createSessionFactory();
47         session = sessionFactory.getSession();
48         createBlobInstances(NUMBER_TO_INSERT);
49         tx = session.currentTransaction();
50         tx.begin();
51         session.deletePersistentAll(BlobTypes.class);
52         tx.commit();
53         // the following tests the delete functionality
54         addTearDownClasses(BlobTypes.class);
55     }
56 
test()57     public void test() {
58         insert();
59         update();
60         failOnError();
61     }
62 
insert()63     protected void insert() {
64         // insert instances
65         tx = session.currentTransaction();
66         tx.begin();
67 
68         int count = 0;
69 
70         for (int i = 0; i < NUMBER_TO_INSERT; ++i) {
71             // must be done with an active transaction
72             session.makePersistent(blobs.get(i));
73             ++count;
74         }
75         tx.commit();
76     }
77 
update()78     protected void update() {
79 
80         tx.begin();
81 
82         for (int i = 1; i < NUMBER_TO_INSERT; ++i) {
83             // must be done with an active transaction
84             BlobTypes e = session.find(BlobTypes.class, i);
85             // see if it is the right one
86             int actualId = e.getId();
87             if (actualId != i) {
88                 error("Expected BlobTypes.id " + i + " but got " + actualId);
89             }
90             byte[] bytes = e.getBlobbytes();
91             // make sure all fields were fetched properly
92             checkBlobBytes("before update", bytes, i, false);
93 
94             int position = getBlobSizeFor(i)/2;
95             // only update if the length is correct
96             if (bytes.length == (position * 2)) {
97                 // modify the byte in the middle of the blob
98                 bytes[position] = (byte)(position % 128);
99                 checkBlobBytes("after update", bytes, i, true);
100 
101                 // mark the field as modified so it will be flushed
102                 session.markModified(e, "blobbytes");
103 
104                 // update the modified instance
105                 session.updatePersistent(e);
106             }
107         }
108         tx.commit();
109         tx.begin();
110 
111         for (int i = 1; i < NUMBER_TO_INSERT; ++i) {
112             // must be done with an active transaction
113             BlobTypes e = session.find(BlobTypes.class, i);
114             // see if it is the right one
115             int actualId = e.getId();
116             if (actualId != i) {
117                 error("Expected BlobTypes.id " + i + " but got " + actualId);
118             }
119             byte[] bytes = e.getBlobbytes();
120 
121             // check to see that the blob field has the right data
122             checkBlobBytes("after commit", e.getBlobbytes(), i, true);
123         }
124         tx.commit();
125     }
126 
createBlobInstances(int number)127     protected void createBlobInstances(int number) {
128         for (int i = 0; i < number; ++i) {
129             BlobTypes instance = session.newInstance(BlobTypes.class);
130             instance.setId(i);
131             int length = getBlobSizeFor(i);
132             instance.setBlobbytes(getBlobBytes(length));
133 //            blob streams are not yet supported
134 //            instance.setBlobstream(getBlobStream(length));
135             blobs.add(instance);
136         }
137     }
138 
139     /** Create a new byte[] of the specified size containing a pattern
140      * of bytes in which each byte is the unsigned value of the index
141      * modulo 256. This pattern is easy to test.
142      * @param size the length of the returned byte[]
143      * @return the byte[] filled with the pattern
144      */
getBlobBytes(int size)145     protected byte[] getBlobBytes(int size) {
146         byte[] result = new byte[size];
147         for (int i = 0; i < size; ++i) {
148             result[i] = (byte)((i % 256) - 128);
149         }
150         return result;
151     }
152 
153     /** Check the byte[] to be sure it matches the pattern in both size
154      * and contents.
155      * @see getBlobBytes
156      * @param bytes the byte[] to check
157      * @param number the expected length of the byte[]
158      */
checkBlobBytes(String where, byte[] bytes, int number, boolean updated)159     protected void checkBlobBytes(String where, byte[] bytes, int number, boolean updated) {
160         // debugging statement; comment out once test passes
161         dumpBlob(where, bytes);
162         int expectedSize = getBlobSizeFor(number);
163         int actualSize = bytes.length;
164         if (expectedSize != actualSize) {
165             error("In " + where
166                     + " wrong size of byte[]; "
167                     + "expected: " + expectedSize
168                     + " actual: " + actualSize);
169         }
170         for (int i = 0; i < actualSize; ++i) {
171             byte expected;
172             int position = expectedSize/2;
173             if (updated && (i == position)) {
174                 expected = (byte)(position % 128);
175             } else {
176                 expected = (byte)((i % 256) - 128);
177             }
178                 byte actual = bytes[i];
179             if (expected != actual) {
180                 error("In " + where + " for size: " + actualSize
181                         + " mismatch in byte[] at position " + i
182                         + " expected: " + expected
183                         + " actual: " + actual);
184             }
185         }
186 
187     }
188 
getBlobStream(final int i)189     protected InputStream getBlobStream(final int i) {
190         return new InputStream() {
191             int size = i;
192             int counter = 0;
193             @Override
194             public int read() throws IOException {
195                 if (counter >= i) {
196                     return -1;
197                 } else {
198                     return counter++ %256;
199                 }
200             }
201         };
202     }
203 
dumpBlob(String where, byte[] blob)204     protected void dumpBlob(String where, byte[] blob) {
205 //        System.out.println("In " + where + " dumpBlob of size: " + blob.length);
206 //        for (byte b: blob) {
207 //            System.out.print("[" + b + "]");
208 //        }
209 //        System.out.println();
210     }
211 
getBlobSizeFor(int i)212     protected int getBlobSizeFor(int i) {
213         int length = (int) Math.pow(2, i);
214         return length;
215     }
216 
217 }
218