--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.db.tests.regression.bugs;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.junit.Test;
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.binding.error.BindingConstructionException;
+import org.simantics.databoard.type.Datatype;
+import org.simantics.databoard.util.binary.RandomAccessBinary;
+import org.simantics.databoard.util.binary.RandomAccessBinary.ByteSide;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.ReadRequest;
+import org.simantics.db.common.request.WriteRequest;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.testing.base.ExistingDatabaseTest;
+import org.simantics.db.testing.impl.Configuration;
+import org.simantics.layer0.Layer0;
+
+public class Issue3176Test2 extends ExistingDatabaseTest {
+
+ @Test
+ public void testRandom() {
+ try {
+ int nBlocks = Configuration.get().i3176BlockCount;
+ int[] blockSize = { 1024, 0xFFFF, 1<<20 };
+ final int LENGTH = blockSize.length;
+ for (int i=0; i<LENGTH; ++i) {
+ testRandom1(blockSize[i], nBlocks);
+ testRandom2(blockSize[i], nBlocks);
+ testRandom3(blockSize[i], nBlocks);
+ }
+ int nBlocksBig = Configuration.get().i3176BigBlockCount;
+ testRandom4(blockSize[blockSize.length - 1], nBlocksBig);
+ } catch (DatabaseException e) {
+ fail("Test failed with exception " + e);
+ }
+ }
+ public void testRandom1(int blockSize, int nBlocks)
+ throws DatabaseException {
+ final RandomTest test = new RandomTest(getSession(), DEBUG, blockSize, nBlocks);
+ Resource r = test.createResource();
+ test.checkNoRandom(r);
+ test.createRandom(r, 0, -1);
+ test.checkLiteralValue(r);
+ test.validateRandom(r, 0, -1);
+ test.modifyRandom(r, 1, -1, false);
+ test.validateRandom(r, 1, -1);
+ test.undoModi(r, 1);
+ test.validateRandom(r, 0, -1);
+ test.removeLiteralValue(r);
+ test.checkNoRandom(r);
+ }
+ public void testRandom2(int blockSize, int nBlocks)
+ throws DatabaseException {
+ final RandomTest test = new RandomTest(getSession(), DEBUG, blockSize, nBlocks);
+ Resource r = test.createResource();
+ test.checkNoRandom(r);
+ test.createRandom(r, 0, -1);
+ test.validateRandom(r, 0, -1);
+ for (int i=1; i<10; ++i) {
+ test.modifyRandom(r, i, -1, false);
+ test.validateRandom(r, i, -1);
+ }
+ test.undoModi(r, 9);
+ test.validateRandom(r, 0, -1);
+ test.removeLiteralValue(r);
+ test.checkNoRandom(r);
+ }
+ public void testRandom3(int blockSize, int nBlocks)
+ throws DatabaseException {
+ final RandomTest test = new RandomTest(getSession(), DEBUG, blockSize, nBlocks);
+ Resource r = test.createResource();
+ test.checkNoRandom(r);
+ test.createRandom(r, 0, -1);
+ test.validateRandom(r, 0, -1);
+ test.truncateRandom(r, 1, 1);
+ test.validateRandom(r, 1, 1);
+ }
+ public void testRandom4(int blockSize, int nBlocks)
+ throws DatabaseException {
+ final RandomTest test = new RandomTest(getSession(), DEBUG, blockSize, nBlocks);
+ Resource r = test.createResource();
+ test.createRandom(r, 0, -1);
+ test.validateRandom(r, 0, -1);
+ test.modifyRandom(r, 1, -1, false);
+ test.validateRandom(r, 1, -1);
+ test.truncateRandom(r, 1, 1);
+ test.validateRandom(r, 1, 1);
+ }
+}
+
+class RandomTest extends Issue3176Test {
+ RandomTest(final Session session, boolean DEBUG, int blockSize, int nBlocks)
+ throws DatabaseException {
+ super(session, DEBUG, blockSize, nBlocks);
+ }
+ void createRandom(final Resource resource, final int inc, final int aBlocks)
+ throws DatabaseException {
+ session.syncRequest(new WriteRequest() {
+ @Override
+ public void perform(WriteGraph graph) throws DatabaseException {
+ graph.markUndoPoint();
+ Layer0 l0 = Layer0.getInstance(graph);
+ Datatype dt;
+ RandomAccessBinary rab;
+ try {
+ dt = Bindings.getBinding(byte[].class).type();
+ rab = graph.createRandomAccessBinary(resource, l0.Literal, dt, null);
+ rab.position(0);
+ } catch (BindingConstructionException e) {
+ throw new DatabaseException("Failed to get datatype for byte array.", e);
+ } catch (IOException e) {
+ throw new DatabaseException("Failed to get new literal for random access binary.", e);
+ }
+ byte[] block = createBlock(BLOCK_SIZE, inc);
+ int T_BLOCKS = aBlocks < 0 ? N_BLOCKS : aBlocks;
+ for (int i=0; i<T_BLOCKS; ++i) {
+ try {
+ rab.write(block);
+ } catch (IOException e) {
+ throw new DatabaseException("Failed to add block i=" + i + ".");
+ }
+ }
+ }
+ });
+ }
+ void modifyRandom(final Resource file, final int inc, final int aBlocks, final boolean validate)
+ throws DatabaseException {
+ session.syncRequest(new WriteRequest() {
+ @Override
+ public void perform(WriteGraph graph) throws DatabaseException {
+ graph.markUndoPoint();
+ Layer0 l0 = Layer0.getInstance(graph);
+ Resource literal = graph.getSingleObject(file, l0.Literal);
+ RandomAccessBinary rab = graph.getRandomAccessBinary(literal);
+ try {
+ rab.position(0);
+ byte[] block = createBlock(BLOCK_SIZE, inc);
+ int T_BLOCKS = aBlocks < 0 ? N_BLOCKS : aBlocks;
+ for (int i=0; i<T_BLOCKS; ++i) {
+ try {
+ rab.write(block);
+ } catch (IOException e) {
+ throw new DatabaseException("Failed to modify block i=" + i + ".");
+ }
+ }
+ if (!validate)
+ return;
+ if (rab.length() != (long)T_BLOCKS * BLOCK_SIZE)
+ new DatabaseException("Failed to validate block size.");
+ rab.position(0);
+ for (int i=0; i<T_BLOCKS; ++i) {
+ rab.readFully(block);
+ for (int j=0; j<BLOCK_SIZE; ++j) {
+ byte b = block[j];
+ if (DEBUG && VERBOSE)
+ System.out.println("DEBUG: Read pos=" + (i*BLOCK_SIZE+j) + " val=" + b);
+ if (b != (byte)(j+inc))
+ throw new DatabaseException("Failed to validate modified file contents.");
+ }
+ }
+ } catch (IOException e) {
+ throw new DatabaseException("Failed to access random binary.", e);
+ }
+ }
+ });
+ }
+ void truncateRandom(final Resource file, final int inc, final int newBlocks)
+ throws DatabaseException {
+ assertTrue(N_BLOCKS > newBlocks);
+ session.syncRequest(new WriteRequest() {
+ @Override
+ public void perform(WriteGraph graph) throws DatabaseException {
+ graph.markUndoPoint();
+ Layer0 l0 = Layer0.getInstance(graph);
+ Resource literal = graph.getSingleObject(file, l0.Literal);
+ RandomAccessBinary rab = graph.getRandomAccessBinary(literal);
+ try {
+ rab.position(0);
+ final int T_BLOCKS = newBlocks < 0 ? N_BLOCKS : newBlocks;
+ byte[] block = createBlock(BLOCK_SIZE, inc);
+ for (int i=0; i<T_BLOCKS; ++i) {
+ try {
+ rab.write(block);
+ } catch (IOException e) {
+ throw new DatabaseException("Failed to modify block i=" + i + ".");
+ }
+ }
+ long bytes = (long)(N_BLOCKS - newBlocks) * BLOCK_SIZE;
+ rab.removeBytes(bytes, ByteSide.Right);
+ } catch (IOException e) {
+ throw new DatabaseException("Failed to access random binary.", e);
+ }
+ }
+ });
+ }
+ void validateRandom(final Resource resource, final int inc, final int newBlocks)
+ throws DatabaseException {
+ session.syncRequest(new ReadRequest() {
+ @Override
+ public void run(ReadGraph graph) throws DatabaseException {
+ Layer0 l0 = Layer0.getInstance(graph);
+ Resource literal = graph.getSingleObject(resource, l0.Literal);
+ RandomAccessBinary rab = graph.getRandomAccessBinary(literal);
+ final long T_BLOCKS = newBlocks < 0 ? N_BLOCKS : newBlocks;
+ try {
+ if (rab.length() != (long)T_BLOCKS * BLOCK_SIZE)
+ new DatabaseException("Failed to validate block size.");
+ rab.position(0);
+ byte[] block = new byte[BLOCK_SIZE];
+ for (int i=0; i<T_BLOCKS; ++i) {
+ rab.readFully(block);
+ for (int j=0; j<BLOCK_SIZE; ++j) {
+ byte b = block[j];
+ if (DEBUG && VERBOSE)
+ System.out.println("DEBUG: Read pos=" + (i*BLOCK_SIZE+j) + " val=" + b);
+ if (b != (byte)(j+inc))
+ throw new DatabaseException("Failed to validate modified file contents.");
+ }
+ }
+ } catch (IOException e) {
+ throw new DatabaseException(e);
+ }
+ }
+ });
+ }
+ void checkNoRandom(final Resource resource)
+ throws DatabaseException {
+ session.syncRequest(new WriteRequest() {
+ @Override
+ public void perform(WriteGraph graph) throws DatabaseException {
+ graph.markUndoPoint();
+ Layer0 l0 = Layer0.getInstance(graph);
+ Resource literal = graph.getPossibleObject(resource, l0.Literal);
+ if (null == literal)
+ return; // No literal.
+ if (!graph.hasValue(literal))
+ return; // No value.
+ try {
+ graph.getRandomAccessBinary(literal);
+ } catch (DatabaseException e) {
+ return; // No random access binary.
+ }
+ throw new DatabaseException("Failed to remove literal value.");
+ }
+ });
+ }
+}
\ No newline at end of file