package org.apache.lucene.store; /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import java.io.IOException; import org.apache.lucene.util.LuceneTestCase; import org.apache.lucene.util.TestUtil; import org.junit.Test; public class TestCopyBytes extends LuceneTestCase { private byte value(int idx) { return (byte) ((idx % 256) * (1 + (idx / 256))); } @Test public void testCopyBytes() throws Exception { int num = atLeast(10); for (int iter = 0; iter < num; iter++) { Directory dir = newDirectory(); if (VERBOSE) { System.out.println("TEST: iter=" + iter + " dir=" + dir); } // make random file IndexOutput out = dir.createOutput("test", newIOContext(random())); byte[] bytes = new byte[TestUtil.nextInt(random(), 1, 77777)]; final int size = TestUtil.nextInt(random(), 1, 1777777); int upto = 0; int byteUpto = 0; while (upto < size) { bytes[byteUpto++] = value(upto); upto++; if (byteUpto == bytes.length) { out.writeBytes(bytes, 0, bytes.length); byteUpto = 0; } } out.writeBytes(bytes, 0, byteUpto); assertEquals(size, out.getFilePointer()); out.close(); assertEquals(size, dir.fileLength("test")); // copy from test -> test2 final IndexInput in = dir.openInput("test", newIOContext(random())); out = dir.createOutput("test2", newIOContext(random())); upto = 0; while (upto < size) { if (random().nextBoolean()) { out.writeByte(in.readByte()); upto++; } else { final int chunk = Math.min( TestUtil.nextInt(random(), 1, bytes.length), size - upto); out.copyBytes(in, chunk); upto += chunk; } } assertEquals(size, upto); out.close(); in.close(); // verify IndexInput in2 = dir.openInput("test2", newIOContext(random())); upto = 0; while (upto < size) { if (random().nextBoolean()) { final byte v = in2.readByte(); assertEquals(value(upto), v); upto++; } else { final int limit = Math.min( TestUtil.nextInt(random(), 1, bytes.length), size - upto); in2.readBytes(bytes, 0, limit); for (int byteIdx = 0; byteIdx < limit; byteIdx++) { assertEquals(value(upto), bytes[byteIdx]); upto++; } } } in2.close(); dir.deleteFile("test"); dir.deleteFile("test2"); dir.close(); } } // LUCENE-3541 public void testCopyBytesWithThreads() throws Exception { int datalen = TestUtil.nextInt(random(), 101, 10000); byte data[] = new byte[datalen]; random().nextBytes(data); Directory d = newDirectory(); IndexOutput output = d.createOutput("data", IOContext.DEFAULT); output.writeBytes(data, 0, datalen); output.close(); IndexInput input = d.openInput("data", IOContext.DEFAULT); IndexOutput outputHeader = d.createOutput("header", IOContext.DEFAULT); // copy our 100-byte header outputHeader.copyBytes(input, 100); outputHeader.close(); // now make N copies of the remaining bytes CopyThread copies[] = new CopyThread[10]; for (int i = 0; i < copies.length; i++) { copies[i] = new CopyThread(input.clone(), d.createOutput("copy" + i, IOContext.DEFAULT)); } for (int i = 0; i < copies.length; i++) { copies[i].start(); } for (int i = 0; i < copies.length; i++) { copies[i].join(); } for (int i = 0; i < copies.length; i++) { IndexInput copiedData = d.openInput("copy" + i, IOContext.DEFAULT); byte[] dataCopy = new byte[datalen]; System.arraycopy(data, 0, dataCopy, 0, 100); // copy the header for easy testing copiedData.readBytes(dataCopy, 100, datalen-100); assertArrayEquals(data, dataCopy); copiedData.close(); } input.close(); d.close(); } static class CopyThread extends Thread { final IndexInput src; final IndexOutput dst; CopyThread(IndexInput src, IndexOutput dst) { this.src = src; this.dst = dst; } @Override public void run() { try { dst.copyBytes(src, src.length()-100); dst.close(); } catch (IOException ex) { throw new RuntimeException(ex); } } } }