| using J2N.IO; |
| using J2N.Numerics; |
| using Lucene.Net.Randomized.Generators; |
| using Lucene.Net.Support; |
| using NUnit.Framework; |
| using System; |
| using System.Collections.Generic; |
| using System.Globalization; |
| using System.IO; |
| using Assert = Lucene.Net.TestFramework.Assert; |
| using Console = Lucene.Net.Util.SystemConsole; |
| |
| namespace Lucene.Net.Util.Packed |
| { |
| /* |
| * 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. |
| */ |
| |
| using Assert = Lucene.Net.TestFramework.Assert; |
| using ByteArrayDataInput = Lucene.Net.Store.ByteArrayDataInput; |
| using CodecUtil = Lucene.Net.Codecs.CodecUtil; |
| using DataInput = Lucene.Net.Store.DataInput; |
| using Directory = Lucene.Net.Store.Directory; |
| using IndexInput = Lucene.Net.Store.IndexInput; |
| using IndexOutput = Lucene.Net.Store.IndexOutput; |
| using IOContext = Lucene.Net.Store.IOContext; |
| using RAMDirectory = Lucene.Net.Store.RAMDirectory; |
| using Reader = Lucene.Net.Util.Packed.PackedInt32s.Reader; |
| |
| [TestFixture] |
| public class TestPackedInts : LuceneTestCase |
| { |
| [Test] |
| public virtual void TestByteCount() |
| { |
| int iters = AtLeast(3); |
| for (int i = 0; i < iters; ++i) |
| { |
| int valueCount = RandomInts.RandomInt32Between(Random, 1, int.MaxValue); |
| foreach (PackedInt32s.Format format in PackedInt32s.Format.Values) |
| { |
| for (int bpv = 1; bpv <= 64; ++bpv) |
| { |
| long byteCount = format.ByteCount(PackedInt32s.VERSION_CURRENT, valueCount, bpv); |
| string msg = "format=" + format + ", byteCount=" + byteCount + ", valueCount=" + valueCount + ", bpv=" + bpv; |
| Assert.IsTrue(byteCount * 8 >= (long)valueCount * bpv, msg); |
| if (format == PackedInt32s.Format.PACKED) |
| { |
| Assert.IsTrue((byteCount - 1) * 8 < (long)valueCount * bpv, msg); |
| } |
| } |
| } |
| } |
| } |
| |
| [Test] |
| public virtual void TestBitsRequired() |
| { |
| Assert.AreEqual(61, PackedInt32s.BitsRequired((long)Math.Pow(2, 61) - 1)); |
| Assert.AreEqual(61, PackedInt32s.BitsRequired(0x1FFFFFFFFFFFFFFFL)); |
| Assert.AreEqual(62, PackedInt32s.BitsRequired(0x3FFFFFFFFFFFFFFFL)); |
| Assert.AreEqual(63, PackedInt32s.BitsRequired(0x7FFFFFFFFFFFFFFFL)); |
| } |
| |
| [Test] |
| public virtual void TestMaxValues() |
| { |
| Assert.AreEqual(1, PackedInt32s.MaxValue(1), "1 bit -> max == 1"); |
| Assert.AreEqual(3, PackedInt32s.MaxValue(2), "2 bit -> max == 3"); |
| Assert.AreEqual(255, PackedInt32s.MaxValue(8), "8 bit -> max == 255"); |
| Assert.AreEqual(long.MaxValue, PackedInt32s.MaxValue(63), "63 bit -> max == Long.MAX_VALUE"); |
| Assert.AreEqual(long.MaxValue, PackedInt32s.MaxValue(64), "64 bit -> max == Long.MAX_VALUE (same as for 63 bit)"); |
| } |
| |
| [Test] |
| public virtual void TestPackedInts_Mem() |
| { |
| int num = AtLeast(3); |
| for (int iter = 0; iter < num; iter++) |
| { |
| for (int nbits = 1; nbits <= 64; nbits++) |
| { |
| long maxValue = PackedInt32s.MaxValue(nbits); |
| int valueCount = TestUtil.NextInt32(Random, 1, 600); |
| int bufferSize = Random.NextBoolean() ? TestUtil.NextInt32(Random, 0, 48) : TestUtil.NextInt32(Random, 0, 4096); |
| Directory d = NewDirectory(); |
| |
| IndexOutput @out = d.CreateOutput("out.bin", NewIOContext(Random)); |
| float acceptableOverhead; |
| if (iter == 0) |
| { |
| // have the first iteration go through exact nbits |
| acceptableOverhead = 0.0f; |
| } |
| else |
| { |
| acceptableOverhead = Random.NextSingle(); |
| } |
| PackedInt32s.Writer w = PackedInt32s.GetWriter(@out, valueCount, nbits, acceptableOverhead); |
| long startFp = @out.GetFilePointer(); |
| |
| int actualValueCount = Random.NextBoolean() ? valueCount : TestUtil.NextInt32(Random, 0, valueCount); |
| long[] values = new long[valueCount]; |
| for (int i = 0; i < actualValueCount; i++) |
| { |
| if (nbits == 64) |
| { |
| values[i] = Random.NextInt64(); |
| } |
| else |
| { |
| values[i] = TestUtil.NextInt64(Random, 0, maxValue); |
| } |
| w.Add(values[i]); |
| } |
| w.Finish(); |
| long fp = @out.GetFilePointer(); |
| @out.Dispose(); |
| |
| // ensure that finish() added the (valueCount-actualValueCount) missing values |
| long bytes = w.Format.ByteCount(PackedInt32s.VERSION_CURRENT, valueCount, w.BitsPerValue); |
| Assert.AreEqual(bytes, fp - startFp); |
| |
| { // test header |
| IndexInput @in = d.OpenInput("out.bin", NewIOContext(Random)); |
| // header = codec header | bitsPerValue | valueCount | format |
| CodecUtil.CheckHeader(@in, PackedInt32s.CODEC_NAME, PackedInt32s.VERSION_START, PackedInt32s.VERSION_CURRENT); // codec header |
| Assert.AreEqual(w.BitsPerValue, @in.ReadVInt32()); |
| Assert.AreEqual(valueCount, @in.ReadVInt32()); |
| Assert.AreEqual(w.Format.Id, @in.ReadVInt32()); |
| Assert.AreEqual(startFp, @in.GetFilePointer()); |
| @in.Dispose(); |
| } |
| |
| { // test reader |
| IndexInput @in = d.OpenInput("out.bin", NewIOContext(Random)); |
| PackedInt32s.Reader r = PackedInt32s.GetReader(@in); |
| Assert.AreEqual(fp, @in.GetFilePointer()); |
| for (int i = 0; i < valueCount; i++) |
| { |
| Assert.AreEqual(values[i], r.Get(i), "index=" + i + " valueCount=" + valueCount + " nbits=" + nbits + " for " + r.GetType().Name); |
| } |
| @in.Dispose(); |
| |
| long expectedBytesUsed = RamUsageEstimator.SizeOf(r); |
| long computedBytesUsed = r.RamBytesUsed(); |
| Assert.AreEqual(expectedBytesUsed, computedBytesUsed, r.GetType() + "expected " + expectedBytesUsed + ", got: " + computedBytesUsed); |
| } |
| |
| { // test reader iterator next |
| IndexInput @in = d.OpenInput("out.bin", NewIOContext(Random)); |
| PackedInt32s.IReaderIterator r = PackedInt32s.GetReaderIterator(@in, bufferSize); |
| for (int i = 0; i < valueCount; i++) |
| { |
| Assert.AreEqual(values[i], r.Next(), "index=" + i + " valueCount=" + valueCount + " nbits=" + nbits + " for " + r.GetType().Name); |
| Assert.AreEqual(i, r.Ord); |
| } |
| assertEquals(fp, @in.GetFilePointer()); |
| @in.Dispose(); |
| } |
| |
| { // test reader iterator bulk next |
| IndexInput @in = d.OpenInput("out.bin", NewIOContext(Random)); |
| PackedInt32s.IReaderIterator r = PackedInt32s.GetReaderIterator(@in, bufferSize); |
| int i = 0; |
| while (i < valueCount) |
| { |
| int count = TestUtil.NextInt32(Random, 1, 95); |
| Int64sRef next = r.Next(count); |
| for (int k = 0; k < next.Length; ++k) |
| { |
| Assert.AreEqual(values[i + k], next.Int64s[next.Offset + k], "index=" + i + " valueCount=" + valueCount + " nbits=" + nbits + " for " + r.GetType().Name); |
| } |
| i += next.Length; |
| } |
| Assert.AreEqual(fp, @in.GetFilePointer()); |
| @in.Dispose(); |
| } |
| |
| { // test direct reader get |
| IndexInput @in = d.OpenInput("out.bin", NewIOContext(Random)); |
| PackedInt32s.Reader intsEnum = PackedInt32s.GetDirectReader(@in); |
| for (int i = 0; i < valueCount; i++) |
| { |
| string msg = "index=" + i + " valueCount=" + valueCount + " nbits=" + nbits + " for " + intsEnum.GetType().Name; |
| int index = Random.Next(valueCount); |
| Assert.AreEqual(values[index], intsEnum.Get(index), msg); |
| } |
| intsEnum.Get(intsEnum.Count - 1); |
| Assert.AreEqual(fp, @in.GetFilePointer()); |
| @in.Dispose(); |
| } |
| d.Dispose(); |
| } |
| } |
| } |
| |
| [Test] |
| public virtual void TestEndPointer() |
| { |
| Directory dir = NewDirectory(); |
| int valueCount = RandomInts.RandomInt32Between(Random, 1, 1000); |
| IndexOutput @out = dir.CreateOutput("tests.bin", NewIOContext(Random)); |
| for (int i = 0; i < valueCount; ++i) |
| { |
| @out.WriteInt64(0); |
| } |
| @out.Dispose(); |
| IndexInput @in = dir.OpenInput("tests.bin", NewIOContext(Random)); |
| for (int version = PackedInt32s.VERSION_START; version <= PackedInt32s.VERSION_CURRENT; ++version) |
| { |
| for (int bpv = 1; bpv <= 64; ++bpv) |
| { |
| foreach (PackedInt32s.Format format in PackedInt32s.Format.Values) |
| { |
| if (!format.IsSupported(bpv)) |
| { |
| continue; |
| } |
| long byteCount = format.ByteCount(version, valueCount, bpv); |
| string msg = "format=" + format + ",version=" + version + ",valueCount=" + valueCount + ",bpv=" + bpv; |
| |
| // test iterator |
| @in.Seek(0L); |
| PackedInt32s.IReaderIterator it = PackedInt32s.GetReaderIteratorNoHeader(@in, format, version, valueCount, bpv, RandomInts.RandomInt32Between(Random, 1, 1 << 16)); |
| for (int i = 0; i < valueCount; ++i) |
| { |
| it.Next(); |
| } |
| Assert.AreEqual(byteCount, @in.GetFilePointer(), msg); |
| |
| // test direct reader |
| @in.Seek(0L); |
| PackedInt32s.Reader directReader = PackedInt32s.GetDirectReaderNoHeader(@in, format, version, valueCount, bpv); |
| directReader.Get(valueCount - 1); |
| Assert.AreEqual(byteCount, @in.GetFilePointer(), msg); |
| |
| // test reader |
| @in.Seek(0L); |
| PackedInt32s.GetReaderNoHeader(@in, format, version, valueCount, bpv); |
| Assert.AreEqual(byteCount, @in.GetFilePointer(), msg); |
| } |
| } |
| } |
| @in.Dispose(); |
| dir.Dispose(); |
| } |
| |
| [Test] |
| public virtual void TestControlledEquality() |
| { |
| const int VALUE_COUNT = 255; |
| const int BITS_PER_VALUE = 8; |
| |
| IList<PackedInt32s.Mutable> packedInts = CreatePackedInts(VALUE_COUNT, BITS_PER_VALUE); |
| foreach (PackedInt32s.Mutable packedInt in packedInts) |
| { |
| for (int i = 0; i < packedInt.Count; i++) |
| { |
| packedInt.Set(i, i + 1); |
| } |
| } |
| AssertListEquality(packedInts); |
| } |
| |
| [Test] |
| public virtual void TestRandomBulkCopy() |
| { |
| int numIters = AtLeast(3); |
| for (int iter = 0; iter < numIters; iter++) |
| { |
| if (Verbose) |
| { |
| Console.WriteLine("\nTEST: iter=" + iter); |
| } |
| int valueCount = AtLeast(100000); |
| int bits1 = TestUtil.NextInt32(Random, 1, 64); |
| int bits2 = TestUtil.NextInt32(Random, 1, 64); |
| if (bits1 > bits2) |
| { |
| int tmp = bits1; |
| bits1 = bits2; |
| bits2 = tmp; |
| } |
| if (Verbose) |
| { |
| Console.WriteLine(" valueCount=" + valueCount + " bits1=" + bits1 + " bits2=" + bits2); |
| } |
| |
| PackedInt32s.Mutable packed1 = PackedInt32s.GetMutable(valueCount, bits1, PackedInt32s.COMPACT); |
| PackedInt32s.Mutable packed2 = PackedInt32s.GetMutable(valueCount, bits2, PackedInt32s.COMPACT); |
| |
| long maxValue = PackedInt32s.MaxValue(bits1); |
| for (int i = 0; i < valueCount; i++) |
| { |
| long val = TestUtil.NextInt64(Random, 0, maxValue); |
| packed1.Set(i, val); |
| packed2.Set(i, val); |
| } |
| |
| long[] buffer = new long[valueCount]; |
| |
| // Copy random slice over, 20 times: |
| for (int iter2 = 0; iter2 < 20; iter2++) |
| { |
| int start = Random.Next(valueCount - 1); |
| int len = TestUtil.NextInt32(Random, 1, valueCount - start); |
| int offset; |
| if (Verbose) |
| { |
| Console.WriteLine(" copy " + len + " values @ " + start); |
| } |
| if (len == valueCount) |
| { |
| offset = 0; |
| } |
| else |
| { |
| offset = Random.Next(valueCount - len); |
| } |
| if (Random.NextBoolean()) |
| { |
| int got = packed1.Get(start, buffer, offset, len); |
| Assert.IsTrue(got <= len); |
| int sot = packed2.Set(start, buffer, offset, got); |
| Assert.IsTrue(sot <= got); |
| } |
| else |
| { |
| PackedInt32s.Copy(packed1, offset, packed2, offset, len, Random.Next(10 * len)); |
| } |
| |
| /* |
| for(int i=0;i<valueCount;i++) { |
| Assert.AreEqual("value " + i, packed1.Get(i), packed2.Get(i)); |
| } |
| */ |
| } |
| |
| for (int i = 0; i < valueCount; i++) |
| { |
| Assert.AreEqual(packed1.Get(i), packed2.Get(i), "value " + i); |
| } |
| } |
| } |
| |
| [Test] |
| public virtual void TestRandomEquality() |
| { |
| int numIters = AtLeast(2); |
| for (int i = 0; i < numIters; ++i) |
| { |
| int valueCount = TestUtil.NextInt32(Random, 1, 300); |
| |
| for (int bitsPerValue = 1; bitsPerValue <= 64; bitsPerValue++) |
| { |
| AssertRandomEquality(valueCount, bitsPerValue, Random.NextInt64()); |
| } |
| } |
| } |
| |
| private static void AssertRandomEquality(int valueCount, int bitsPerValue, long randomSeed) |
| { |
| IList<PackedInt32s.Mutable> packedInts = CreatePackedInts(valueCount, bitsPerValue); |
| foreach (PackedInt32s.Mutable packedInt in packedInts) |
| { |
| try |
| { |
| Fill(packedInt, PackedInt32s.MaxValue(bitsPerValue), randomSeed); |
| } |
| catch (Exception e) |
| { |
| Console.Error.WriteLine(e.StackTrace); |
| Assert.Fail(string.Format(CultureInfo.InvariantCulture, "Exception while filling {0}: valueCount={1}, bitsPerValue={2}", packedInt.GetType().Name, valueCount, bitsPerValue)); |
| } |
| } |
| AssertListEquality(packedInts); |
| } |
| |
| private static IList<PackedInt32s.Mutable> CreatePackedInts(int valueCount, int bitsPerValue) |
| { |
| IList<PackedInt32s.Mutable> packedInts = new List<PackedInt32s.Mutable>(); |
| if (bitsPerValue <= 8) |
| { |
| packedInts.Add(new Direct8(valueCount)); |
| } |
| if (bitsPerValue <= 16) |
| { |
| packedInts.Add(new Direct16(valueCount)); |
| } |
| if (bitsPerValue <= 24 && valueCount <= Packed8ThreeBlocks.MAX_SIZE) |
| { |
| packedInts.Add(new Packed8ThreeBlocks(valueCount)); |
| } |
| if (bitsPerValue <= 32) |
| { |
| packedInts.Add(new Direct32(valueCount)); |
| } |
| if (bitsPerValue <= 48 && valueCount <= Packed16ThreeBlocks.MAX_SIZE) |
| { |
| packedInts.Add(new Packed16ThreeBlocks(valueCount)); |
| } |
| if (bitsPerValue <= 63) |
| { |
| packedInts.Add(new Packed64(valueCount, bitsPerValue)); |
| } |
| packedInts.Add(new Direct64(valueCount)); |
| for (int bpv = bitsPerValue; bpv <= Packed64SingleBlock.MAX_SUPPORTED_BITS_PER_VALUE; ++bpv) |
| { |
| if (Packed64SingleBlock.IsSupported(bpv)) |
| { |
| packedInts.Add(Packed64SingleBlock.Create(valueCount, bpv)); |
| } |
| } |
| return packedInts; |
| } |
| |
| private static void Fill(PackedInt32s.Mutable packedInt, long maxValue, long randomSeed) |
| { |
| Random rnd2 = new Random((int)randomSeed); |
| for (int i = 0; i < packedInt.Count; i++) |
| { |
| long value = TestUtil.NextInt64(rnd2, 0, maxValue); |
| packedInt.Set(i, value); |
| Assert.AreEqual(value, packedInt.Get(i), string.Format(CultureInfo.InvariantCulture, "The set/get of the value at index {0} should match for {1}", i, packedInt.GetType().Name)); |
| } |
| } |
| |
| private static void AssertListEquality<T1>(IList<T1> packedInts) where T1 : PackedInt32s.Reader |
| { |
| AssertListEquality("", packedInts); |
| } |
| |
| private static void AssertListEquality<T1>(string message, IList<T1> packedInts) where T1 : PackedInt32s.Reader |
| { |
| if (packedInts.Count == 0) |
| { |
| return; |
| } |
| PackedInt32s.Reader @base = packedInts[0]; |
| int valueCount = @base.Count; |
| foreach (PackedInt32s.Reader packedInt in packedInts) |
| { |
| Assert.AreEqual(valueCount, packedInt.Count, message + ". The number of values should be the same "); |
| } |
| for (int i = 0; i < valueCount; i++) |
| { |
| for (int j = 1; j < packedInts.Count; j++) |
| { |
| Assert.AreEqual( @base.Get(i), packedInts[j].Get(i), string.Format(CultureInfo.InvariantCulture, "{0}. The value at index {1} should be the same for {2} and {3}", message, i, @base.GetType().Name, packedInts[j].GetType().Name)); |
| } |
| } |
| } |
| |
| [Test] |
| public virtual void TestSingleValue() |
| { |
| for (int bitsPerValue = 1; bitsPerValue <= 64; ++bitsPerValue) |
| { |
| Directory dir = NewDirectory(); |
| IndexOutput @out = dir.CreateOutput("out", NewIOContext(Random)); |
| PackedInt32s.Writer w = PackedInt32s.GetWriter(@out, 1, bitsPerValue, PackedInt32s.DEFAULT); |
| long value = 17L & PackedInt32s.MaxValue(bitsPerValue); |
| w.Add(value); |
| w.Finish(); |
| long end = @out.GetFilePointer(); |
| @out.Dispose(); |
| |
| IndexInput @in = dir.OpenInput("out", NewIOContext(Random)); |
| Reader reader = PackedInt32s.GetReader(@in); |
| string msg = "Impl=" + w.GetType().Name + ", bitsPerValue=" + bitsPerValue; |
| Assert.AreEqual(1, reader.Count, msg); |
| Assert.AreEqual(value, reader.Get(0), msg); |
| Assert.AreEqual(end, @in.GetFilePointer(), msg); |
| @in.Dispose(); |
| |
| dir.Dispose(); |
| } |
| } |
| |
| [Test] |
| public virtual void TestSecondaryBlockChange() |
| { |
| PackedInt32s.Mutable mutable = new Packed64(26, 5); |
| mutable.Set(24, 31); |
| Assert.AreEqual(31, mutable.Get(24), "The value #24 should be correct"); |
| mutable.Set(4, 16); |
| Assert.AreEqual(31, mutable.Get(24), "The value #24 should remain unchanged"); |
| } |
| |
| /* |
| Check if the structures properly handle the case where |
| index * bitsPerValue > Integer.MAX_VALUE |
| |
| NOTE: this test allocates 256 MB |
| */ |
| [Ignore("See LUCENE-4488 - LUCENENET NOTE: In .NET it is not possible to catch OOME")] |
| [Test] |
| public virtual void TestIntOverflow() |
| { |
| int INDEX = (int)Math.Pow(2, 30) + 1; |
| int BITS = 2; |
| |
| Packed64 p64 = null; |
| try |
| { |
| p64 = new Packed64(INDEX, BITS); |
| } |
| #pragma warning disable 168 |
| catch (OutOfMemoryException oome) |
| #pragma warning restore 168 |
| { |
| // this can easily happen: we're allocating a |
| // long[] that needs 256-273 MB. Heap is 512 MB, |
| // but not all of that is available for large |
| // objects ... empirical testing shows we only |
| // have ~ 67 MB free. |
| } |
| if (p64 != null) |
| { |
| p64.Set(INDEX - 1, 1); |
| Assert.AreEqual(1, p64.Get(INDEX - 1), "The value at position " + (INDEX - 1) + " should be correct for Packed64"); |
| p64 = null; |
| } |
| |
| Packed64SingleBlock p64sb = null; |
| try |
| { |
| p64sb = Packed64SingleBlock.Create(INDEX, BITS); |
| } |
| #pragma warning disable 168 |
| catch (OutOfMemoryException oome) |
| #pragma warning restore 168 |
| { |
| // Ignore: see comment above |
| } |
| if (p64sb != null) |
| { |
| p64sb.Set(INDEX - 1, 1); |
| Assert.AreEqual(1, p64sb.Get(INDEX - 1), "The value at position " + (INDEX - 1) + " should be correct for " + p64sb.GetType().Name); |
| } |
| |
| int index = int.MaxValue / 24 + 1; |
| Packed8ThreeBlocks p8 = null; |
| try |
| { |
| p8 = new Packed8ThreeBlocks(index); |
| } |
| #pragma warning disable 168 |
| catch (OutOfMemoryException oome) |
| #pragma warning restore 168 |
| { |
| // Ignore: see comment above |
| } |
| if (p8 != null) |
| { |
| p8.Set(index - 1, 1); |
| Assert.AreEqual(1, p8.Get(index - 1), "The value at position " + (index - 1) + " should be correct for Packed8ThreeBlocks"); |
| p8 = null; |
| } |
| |
| index = int.MaxValue / 48 + 1; |
| Packed16ThreeBlocks p16 = null; |
| try |
| { |
| p16 = new Packed16ThreeBlocks(index); |
| } |
| #pragma warning disable 168 |
| catch (OutOfMemoryException oome) |
| #pragma warning restore 168 |
| { |
| // Ignore: see comment above |
| } |
| if (p16 != null) |
| { |
| p16.Set(index - 1, 1); |
| Assert.AreEqual(1, p16.Get(index - 1), "The value at position " + (index - 1) + " should be correct for Packed16ThreeBlocks"); |
| p16 = null; |
| } |
| } |
| |
| [Test] |
| public virtual void TestFill() |
| { |
| const int valueCount = 1111; |
| int from = Random.Next(valueCount + 1); |
| int to = from + Random.Next(valueCount + 1 - from); |
| for (int bpv = 1; bpv <= 64; ++bpv) |
| { |
| long val = TestUtil.NextInt64(Random, 0, PackedInt32s.MaxValue(bpv)); |
| IList<PackedInt32s.Mutable> packedInts = CreatePackedInts(valueCount, bpv); |
| foreach (PackedInt32s.Mutable ints in packedInts) |
| { |
| string msg = ints.GetType().Name + " bpv=" + bpv + ", from=" + from + ", to=" + to + ", val=" + val; |
| ints.Fill(0, ints.Count, 1); |
| ints.Fill(from, to, val); |
| for (int i = 0; i < ints.Count; ++i) |
| { |
| if (i >= from && i < to) |
| { |
| Assert.AreEqual(val, ints.Get(i), msg + ", i=" + i); |
| } |
| else |
| { |
| Assert.AreEqual(1, ints.Get(i), msg + ", i=" + i); |
| } |
| } |
| } |
| } |
| } |
| |
| [Test] |
| public virtual void TestPackedIntsNull() |
| { |
| // must be > 10 for the bulk reads below |
| int size = TestUtil.NextInt32(Random, 11, 256); |
| Reader packedInts = new PackedInt32s.NullReader(size); |
| Assert.AreEqual(0, packedInts.Get(TestUtil.NextInt32(Random, 0, size - 1))); |
| long[] arr = new long[size + 10]; |
| int r; |
| Arrays.Fill(arr, 1); |
| r = packedInts.Get(0, arr, 0, size - 1); |
| Assert.AreEqual(size - 1, r); |
| for (r--; r >= 0; r--) |
| { |
| Assert.AreEqual(0, arr[r]); |
| } |
| Arrays.Fill(arr, 1); |
| r = packedInts.Get(10, arr, 0, size + 10); |
| Assert.AreEqual(size - 10, r); |
| for (int i = 0; i < size - 10; i++) |
| { |
| Assert.AreEqual(0, arr[i]); |
| } |
| |
| } |
| |
| [Test] |
| public virtual void TestBulkGet() |
| { |
| const int valueCount = 1111; |
| int index = Random.Next(valueCount); |
| int len = TestUtil.NextInt32(Random, 1, valueCount * 2); |
| int off = Random.Next(77); |
| |
| for (int bpv = 1; bpv <= 64; ++bpv) |
| { |
| long mask = PackedInt32s.MaxValue(bpv); |
| IList<PackedInt32s.Mutable> packedInts = CreatePackedInts(valueCount, bpv); |
| |
| foreach (PackedInt32s.Mutable ints in packedInts) |
| { |
| for (int i = 0; i < ints.Count; ++i) |
| { |
| ints.Set(i, (31L * i - 1099) & mask); |
| } |
| long[] arr = new long[off + len]; |
| |
| string msg = ints.GetType().Name + " valueCount=" + valueCount + ", index=" + index + ", len=" + len + ", off=" + off; |
| int gets = ints.Get(index, arr, off, len); |
| Assert.IsTrue(gets > 0, msg); |
| Assert.IsTrue(gets <= len, msg); |
| Assert.IsTrue(gets <= ints.Count - index, msg); |
| |
| for (int i = 0; i < arr.Length; ++i) |
| { |
| string m = msg + ", i=" + i; |
| if (i >= off && i < off + gets) |
| { |
| Assert.AreEqual(ints.Get(i - off + index), arr[i], m); |
| } |
| else |
| { |
| Assert.AreEqual(0, arr[i], m); |
| } |
| } |
| } |
| } |
| } |
| |
| [Test] |
| public virtual void TestBulkSet() |
| { |
| const int valueCount = 1111; |
| int index = Random.Next(valueCount); |
| int len = TestUtil.NextInt32(Random, 1, valueCount * 2); |
| int off = Random.Next(77); |
| long[] arr = new long[off + len]; |
| |
| for (int bpv = 1; bpv <= 64; ++bpv) |
| { |
| long mask = PackedInt32s.MaxValue(bpv); |
| IList<PackedInt32s.Mutable> packedInts = CreatePackedInts(valueCount, bpv); |
| for (int i = 0; i < arr.Length; ++i) |
| { |
| arr[i] = (31L * i + 19) & mask; |
| } |
| |
| foreach (PackedInt32s.Mutable ints in packedInts) |
| { |
| string msg = ints.GetType().Name + " valueCount=" + valueCount + ", index=" + index + ", len=" + len + ", off=" + off; |
| int sets = ints.Set(index, arr, off, len); |
| Assert.IsTrue(sets > 0, msg); |
| Assert.IsTrue(sets <= len, msg); |
| |
| for (int i = 0; i < ints.Count; ++i) |
| { |
| string m = msg + ", i=" + i; |
| if (i >= index && i < index + sets) |
| { |
| Assert.AreEqual(arr[off - index + i], ints.Get(i), m); |
| } |
| else |
| { |
| Assert.AreEqual(0, ints.Get(i), m); |
| } |
| } |
| } |
| } |
| } |
| |
| [Test] |
| public virtual void TestCopy() |
| { |
| int valueCount = TestUtil.NextInt32(Random, 5, 600); |
| int off1 = Random.Next(valueCount); |
| int off2 = Random.Next(valueCount); |
| int len = Random.Next(Math.Min(valueCount - off1, valueCount - off2)); |
| int mem = Random.Next(1024); |
| |
| for (int bpv = 1; bpv <= 64; ++bpv) |
| { |
| long mask = PackedInt32s.MaxValue(bpv); |
| foreach (PackedInt32s.Mutable r1 in CreatePackedInts(valueCount, bpv)) |
| { |
| for (int i = 0; i < r1.Count; ++i) |
| { |
| r1.Set(i, (31L * i - 1023) & mask); |
| } |
| foreach (PackedInt32s.Mutable r2 in CreatePackedInts(valueCount, bpv)) |
| { |
| string msg = "src=" + r1 + ", dest=" + r2 + ", srcPos=" + off1 + ", destPos=" + off2 + ", len=" + len + ", mem=" + mem; |
| PackedInt32s.Copy(r1, off1, r2, off2, len, mem); |
| for (int i = 0; i < r2.Count; ++i) |
| { |
| string m = msg + ", i=" + i; |
| if (i >= off2 && i < off2 + len) |
| { |
| Assert.AreEqual(r1.Get(i - off2 + off1), r2.Get(i), m); |
| } |
| else |
| { |
| Assert.AreEqual(0, r2.Get(i), m); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| [Test] |
| public virtual void TestGrowableWriter() |
| { |
| int valueCount = 113 + Random.Next(1111); |
| GrowableWriter wrt = new GrowableWriter(1, valueCount, PackedInt32s.DEFAULT); |
| wrt.Set(4, 2); |
| wrt.Set(7, 10); |
| wrt.Set(valueCount - 10, 99); |
| wrt.Set(99, 999); |
| wrt.Set(valueCount - 1, 1 << 10); |
| Assert.AreEqual(1 << 10, wrt.Get(valueCount - 1)); |
| wrt.Set(99, (1 << 23) - 1); |
| Assert.AreEqual(1 << 10, wrt.Get(valueCount - 1)); |
| wrt.Set(1, long.MaxValue); |
| wrt.Set(2, -3); |
| Assert.AreEqual(64, wrt.BitsPerValue); |
| Assert.AreEqual(1 << 10, wrt.Get(valueCount - 1)); |
| Assert.AreEqual(long.MaxValue, wrt.Get(1)); |
| Assert.AreEqual(-3L, wrt.Get(2)); |
| Assert.AreEqual(2, wrt.Get(4)); |
| Assert.AreEqual((1 << 23) - 1, wrt.Get(99)); |
| Assert.AreEqual(10, wrt.Get(7)); |
| Assert.AreEqual(99, wrt.Get(valueCount - 10)); |
| Assert.AreEqual(1 << 10, wrt.Get(valueCount - 1)); |
| Assert.AreEqual(RamUsageEstimator.SizeOf(wrt), wrt.RamBytesUsed()); |
| } |
| |
| [Test] |
| public virtual void TestPagedGrowableWriter() |
| { |
| int pageSize = 1 << (TestUtil.NextInt32(Random, 6, 30)); |
| // supports 0 values? |
| PagedGrowableWriter writer = new PagedGrowableWriter(0, pageSize, TestUtil.NextInt32(Random, 1, 64), Random.NextSingle()); |
| Assert.AreEqual(0, writer.Count); |
| |
| // compare against AppendingDeltaPackedLongBuffer |
| AppendingDeltaPackedInt64Buffer buf = new AppendingDeltaPackedInt64Buffer(); |
| int size = Random.Next(1000000); |
| long max = 5; |
| for (int i = 0; i < size; ++i) |
| { |
| buf.Add(TestUtil.NextInt64(Random, 0, max)); |
| if (Rarely()) |
| { |
| max = PackedInt32s.MaxValue(Rarely() ? TestUtil.NextInt32(Random, 0, 63) : TestUtil.NextInt32(Random, 0, 31)); |
| } |
| } |
| writer = new PagedGrowableWriter(size, pageSize, TestUtil.NextInt32(Random, 1, 64), Random.NextSingle()); |
| Assert.AreEqual(size, writer.Count); |
| for (int i = size - 1; i >= 0; --i) |
| { |
| writer.Set(i, buf.Get(i)); |
| } |
| for (int i = 0; i < size; ++i) |
| { |
| Assert.AreEqual(buf.Get(i), writer.Get(i)); |
| } |
| |
| // test ramBytesUsed |
| Assert.AreEqual(RamUsageEstimator.SizeOf(writer), writer.RamBytesUsed(), 8); |
| |
| // test copy |
| PagedGrowableWriter copy = writer.Resize(TestUtil.NextInt64(Random, writer.Count / 2, writer.Count * 3 / 2)); |
| for (long i = 0; i < copy.Count; ++i) |
| { |
| if (i < writer.Count) |
| { |
| Assert.AreEqual(writer.Get(i), copy.Get(i)); |
| } |
| else |
| { |
| Assert.AreEqual(0, copy.Get(i)); |
| } |
| } |
| |
| // test grow |
| PagedGrowableWriter grow = writer.Grow(TestUtil.NextInt64(Random, writer.Count / 2, writer.Count * 3 / 2)); |
| for (long i = 0; i < grow.Count; ++i) |
| { |
| if (i < writer.Count) |
| { |
| Assert.AreEqual(writer.Get(i), grow.Get(i)); |
| } |
| else |
| { |
| Assert.AreEqual(0, grow.Get(i)); |
| } |
| } |
| } |
| |
| [Test] |
| public virtual void TestPagedMutable() |
| { |
| int bitsPerValue = TestUtil.NextInt32(Random, 1, 64); |
| long max = PackedInt32s.MaxValue(bitsPerValue); |
| int pageSize = 1 << (TestUtil.NextInt32(Random, 6, 30)); |
| // supports 0 values? |
| PagedMutable writer = new PagedMutable(0, pageSize, bitsPerValue, Random.NextSingle() / 2); |
| Assert.AreEqual(0, writer.Count); |
| |
| // compare against AppendingDeltaPackedLongBuffer |
| AppendingDeltaPackedInt64Buffer buf = new AppendingDeltaPackedInt64Buffer(); |
| int size = Random.Next(1000000); |
| |
| for (int i = 0; i < size; ++i) |
| { |
| buf.Add(bitsPerValue == 64 ? Random.NextInt64() : TestUtil.NextInt64(Random, 0, max)); |
| } |
| writer = new PagedMutable(size, pageSize, bitsPerValue, Random.NextSingle()); |
| Assert.AreEqual(size, writer.Count); |
| for (int i = size - 1; i >= 0; --i) |
| { |
| writer.Set(i, buf.Get(i)); |
| } |
| for (int i = 0; i < size; ++i) |
| { |
| Assert.AreEqual(buf.Get(i), writer.Get(i)); |
| } |
| |
| // test ramBytesUsed |
| Assert.AreEqual(RamUsageEstimator.SizeOf(writer) - RamUsageEstimator.SizeOf(writer.format), writer.RamBytesUsed()); |
| |
| // test copy |
| PagedMutable copy = writer.Resize(TestUtil.NextInt64(Random, writer.Count / 2, writer.Count * 3 / 2)); |
| for (long i = 0; i < copy.Count; ++i) |
| { |
| if (i < writer.Count) |
| { |
| Assert.AreEqual(writer.Get(i), copy.Get(i)); |
| } |
| else |
| { |
| Assert.AreEqual(0, copy.Get(i)); |
| } |
| } |
| |
| // test grow |
| PagedMutable grow = writer.Grow(TestUtil.NextInt64(Random, writer.Count / 2, writer.Count * 3 / 2)); |
| for (long i = 0; i < grow.Count; ++i) |
| { |
| if (i < writer.Count) |
| { |
| Assert.AreEqual(writer.Get(i), grow.Get(i)); |
| } |
| else |
| { |
| Assert.AreEqual(0, grow.Get(i)); |
| } |
| } |
| } |
| |
| [Ignore("// memory hole")] |
| [Test] |
| public virtual void TestPagedGrowableWriterOverflow() |
| { |
| long size = TestUtil.NextInt64(Random, 2 * (long)int.MaxValue, 3 * (long)int.MaxValue); |
| int pageSize = 1 << (TestUtil.NextInt32(Random, 16, 30)); |
| PagedGrowableWriter writer = new PagedGrowableWriter(size, pageSize, 1, Random.NextSingle()); |
| long index = TestUtil.NextInt64(Random, (long)int.MaxValue, size - 1); |
| writer.Set(index, 2); |
| Assert.AreEqual(2, writer.Get(index)); |
| for (int i = 0; i < 1000000; ++i) |
| { |
| long idx = TestUtil.NextInt64(Random, 0, size); |
| if (idx == index) |
| { |
| Assert.AreEqual(2, writer.Get(idx)); |
| } |
| else |
| { |
| Assert.AreEqual(0, writer.Get(idx)); |
| } |
| } |
| } |
| |
| [Test] |
| public virtual void TestSave() |
| { |
| int valueCount = TestUtil.NextInt32(Random, 1, 2048); |
| for (int bpv = 1; bpv <= 64; ++bpv) |
| { |
| int maxValue = (int)Math.Min(PackedInt32s.MaxValue(31), PackedInt32s.MaxValue(bpv)); |
| RAMDirectory directory = new RAMDirectory(); |
| IList<PackedInt32s.Mutable> packedInts = CreatePackedInts(valueCount, bpv); |
| foreach (PackedInt32s.Mutable mutable in packedInts) |
| { |
| for (int i = 0; i < mutable.Count; ++i) |
| { |
| mutable.Set(i, Random.Next(maxValue)); |
| } |
| |
| IndexOutput @out = directory.CreateOutput("packed-ints.bin", IOContext.DEFAULT); |
| mutable.Save(@out); |
| @out.Dispose(); |
| |
| IndexInput @in = directory.OpenInput("packed-ints.bin", IOContext.DEFAULT); |
| PackedInt32s.Reader reader = PackedInt32s.GetReader(@in); |
| Assert.AreEqual(mutable.BitsPerValue, reader.BitsPerValue); |
| Assert.AreEqual(valueCount, reader.Count); |
| if (mutable is Packed64SingleBlock) |
| { |
| // make sure that we used the right format so that the reader has |
| // the same performance characteristics as the mutable that has been |
| // serialized |
| Assert.IsTrue(reader is Packed64SingleBlock); |
| } |
| else |
| { |
| Assert.IsFalse(reader is Packed64SingleBlock); |
| } |
| for (int i = 0; i < valueCount; ++i) |
| { |
| Assert.AreEqual(mutable.Get(i), reader.Get(i)); |
| } |
| @in.Dispose(); |
| directory.DeleteFile("packed-ints.bin"); |
| } |
| directory.Dispose(); |
| } |
| } |
| |
| [Test] |
| public virtual void TestEncodeDecode() |
| { |
| foreach (PackedInt32s.Format format in PackedInt32s.Format.Values) |
| { |
| for (int bpv = 1; bpv <= 64; ++bpv) |
| { |
| if (!format.IsSupported(bpv)) |
| { |
| continue; |
| } |
| string msg = format + " " + bpv; |
| |
| PackedInt32s.IEncoder encoder = PackedInt32s.GetEncoder(format, PackedInt32s.VERSION_CURRENT, bpv); |
| PackedInt32s.IDecoder decoder = PackedInt32s.GetDecoder(format, PackedInt32s.VERSION_CURRENT, bpv); |
| int longBlockCount = encoder.Int64BlockCount; |
| int longValueCount = encoder.Int64ValueCount; |
| int byteBlockCount = encoder.ByteBlockCount; |
| int byteValueCount = encoder.ByteValueCount; |
| Assert.AreEqual(longBlockCount, decoder.Int64BlockCount); |
| Assert.AreEqual(longValueCount, decoder.Int64ValueCount); |
| Assert.AreEqual(byteBlockCount, decoder.ByteBlockCount); |
| Assert.AreEqual(byteValueCount, decoder.ByteValueCount); |
| |
| int longIterations = Random.Next(100); |
| int byteIterations = longIterations * longValueCount / byteValueCount; |
| Assert.AreEqual(longIterations * longValueCount, byteIterations * byteValueCount); |
| int blocksOffset = Random.Next(100); |
| int valuesOffset = Random.Next(100); |
| int blocksOffset2 = Random.Next(100); |
| int blocksLen = longIterations * longBlockCount; |
| |
| // 1. generate random inputs |
| long[] blocks = new long[blocksOffset + blocksLen]; |
| for (int i = 0; i < blocks.Length; ++i) |
| { |
| blocks[i] = Random.NextInt64(); |
| if (format == PackedInt32s.Format.PACKED_SINGLE_BLOCK && 64 % bpv != 0) |
| { |
| // clear highest bits for packed |
| int toClear = 64 % bpv; |
| blocks[i] = (blocks[i] << toClear).TripleShift(toClear); |
| } |
| } |
| |
| // 2. decode |
| long[] values = new long[valuesOffset + longIterations * longValueCount]; |
| decoder.Decode(blocks, blocksOffset, values, valuesOffset, longIterations); |
| foreach (long value in values) |
| { |
| Assert.IsTrue(value <= PackedInt32s.MaxValue(bpv)); |
| } |
| // test decoding to int[] |
| int[] intValues; |
| if (bpv <= 32) |
| { |
| intValues = new int[values.Length]; |
| decoder.Decode(blocks, blocksOffset, intValues, valuesOffset, longIterations); |
| Assert.IsTrue(Equals(intValues, values)); |
| } |
| else |
| { |
| intValues = null; |
| } |
| |
| // 3. re-encode |
| long[] blocks2 = new long[blocksOffset2 + blocksLen]; |
| encoder.Encode(values, valuesOffset, blocks2, blocksOffset2, longIterations); |
| Assert.AreEqual(Arrays.CopyOfRange(blocks, blocksOffset, blocks.Length), Arrays.CopyOfRange(blocks2, blocksOffset2, blocks2.Length), msg); |
| // test encoding from int[] |
| if (bpv <= 32) |
| { |
| long[] blocks3 = new long[blocks2.Length]; |
| encoder.Encode(intValues, valuesOffset, blocks3, blocksOffset2, longIterations); |
| Assert.AreEqual(blocks2, blocks3, msg); |
| } |
| |
| // 4. byte[] decoding |
| byte[] byteBlocks = new byte[8 * blocks.Length]; |
| ByteBuffer.Wrap(byteBlocks).AsInt64Buffer().Put(blocks); |
| long[] values2 = new long[valuesOffset + longIterations * longValueCount]; |
| decoder.Decode(byteBlocks, blocksOffset * 8, values2, valuesOffset, byteIterations); |
| foreach (long value in values2) |
| { |
| Assert.IsTrue(value <= PackedInt32s.MaxValue(bpv), msg); |
| } |
| Assert.AreEqual(values, values2, msg); |
| // test decoding to int[] |
| if (bpv <= 32) |
| { |
| int[] intValues2 = new int[values2.Length]; |
| decoder.Decode(byteBlocks, blocksOffset * 8, intValues2, valuesOffset, byteIterations); |
| Assert.IsTrue(Equals(intValues2, values2), msg); |
| } |
| |
| // 5. byte[] encoding |
| byte[] blocks3_ = new byte[8 * (blocksOffset2 + blocksLen)]; |
| encoder.Encode(values, valuesOffset, blocks3_, 8 * blocksOffset2, byteIterations); |
| assertEquals(msg, Int64Buffer.Wrap(blocks2), ByteBuffer.Wrap(blocks3_).AsInt64Buffer()); |
| // test encoding from int[] |
| if (bpv <= 32) |
| { |
| byte[] blocks4 = new byte[blocks3_.Length]; |
| encoder.Encode(intValues, valuesOffset, blocks4, 8 * blocksOffset2, byteIterations); |
| Assert.AreEqual(blocks3_, blocks4, msg); |
| } |
| } |
| } |
| } |
| |
| private static bool Equals(int[] ints, long[] longs) |
| { |
| if (ints.Length != longs.Length) |
| { |
| return false; |
| } |
| for (int i = 0; i < ints.Length; ++i) |
| { |
| if ((ints[i] & 0xFFFFFFFFL) != longs[i]) |
| { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| internal enum DataType |
| { |
| PACKED, |
| DELTA_PACKED, |
| MONOTONIC |
| } |
| |
| |
| [Test] |
| public virtual void TestAppendingLongBuffer() |
| { |
| |
| long[] arr = new long[RandomInts.RandomInt32Between(Random, 1, 1000000)]; |
| float[] ratioOptions = new float[] { PackedInt32s.DEFAULT, PackedInt32s.COMPACT, PackedInt32s.FAST }; |
| foreach (int bpv in new int[] { 0, 1, 63, 64, RandomInts.RandomInt32Between(Random, 2, 62) }) |
| { |
| foreach (DataType dataType in Enum.GetValues(typeof(DataType))) |
| { |
| int pageSize = 1 << TestUtil.NextInt32(Random, 6, 20); |
| int initialPageCount = TestUtil.NextInt32(Random, 0, 16); |
| float acceptableOverheadRatio = ratioOptions[TestUtil.NextInt32(Random, 0, ratioOptions.Length - 1)]; |
| AbstractAppendingInt64Buffer buf; |
| int inc; |
| switch (dataType) |
| { |
| case Lucene.Net.Util.Packed.TestPackedInts.DataType.PACKED: |
| buf = new AppendingPackedInt64Buffer(initialPageCount, pageSize, acceptableOverheadRatio); |
| inc = 0; |
| break; |
| case Lucene.Net.Util.Packed.TestPackedInts.DataType.DELTA_PACKED: |
| buf = new AppendingDeltaPackedInt64Buffer(initialPageCount, pageSize, acceptableOverheadRatio); |
| inc = 0; |
| break; |
| case Lucene.Net.Util.Packed.TestPackedInts.DataType.MONOTONIC: |
| buf = new MonotonicAppendingInt64Buffer(initialPageCount, pageSize, acceptableOverheadRatio); |
| inc = TestUtil.NextInt32(Random, -1000, 1000); |
| break; |
| default: |
| throw new Exception("added a type and forgot to add it here?"); |
| |
| } |
| |
| if (bpv == 0) |
| { |
| arr[0] = Random.NextInt64(); |
| for (int i = 1; i < arr.Length; ++i) |
| { |
| arr[i] = arr[i - 1] + inc; |
| } |
| } |
| else if (bpv == 64) |
| { |
| for (int i = 0; i < arr.Length; ++i) |
| { |
| arr[i] = Random.NextInt64(); |
| } |
| } |
| else |
| { |
| long minValue = TestUtil.NextInt64(Random, long.MinValue, long.MaxValue - PackedInt32s.MaxValue(bpv)); |
| for (int i = 0; i < arr.Length; ++i) |
| { |
| arr[i] = minValue + inc * i + Random.NextInt64() & PackedInt32s.MaxValue(bpv); // TestUtil.nextLong is too slow |
| } |
| } |
| |
| for (int i = 0; i < arr.Length; ++i) |
| { |
| buf.Add(arr[i]); |
| } |
| Assert.AreEqual(arr.Length, buf.Count); |
| if (Random.NextBoolean()) |
| { |
| buf.Freeze(); |
| if (Random.NextBoolean()) |
| { |
| // Make sure double freeze doesn't break anything |
| buf.Freeze(); |
| } |
| } |
| Assert.AreEqual(arr.Length, buf.Count); |
| |
| for (int i = 0; i < arr.Length; ++i) |
| { |
| Assert.AreEqual(arr[i], buf.Get(i)); |
| } |
| |
| AbstractAppendingInt64Buffer.Iterator it = buf.GetIterator(); |
| for (int i = 0; i < arr.Length; ++i) |
| { |
| if (Random.NextBoolean()) |
| { |
| Assert.IsTrue(it.HasNext); |
| } |
| Assert.AreEqual(arr[i], it.Next()); |
| } |
| Assert.IsFalse(it.HasNext); |
| |
| |
| long[] target = new long[arr.Length + 1024]; // check the request for more is OK. |
| for (int i = 0; i < arr.Length; i += TestUtil.NextInt32(Random, 0, 10000)) |
| { |
| int lenToRead = Random.Next(buf.PageSize * 2) + 1; |
| lenToRead = Math.Min(lenToRead, target.Length - i); |
| int lenToCheck = Math.Min(lenToRead, arr.Length - i); |
| int off = i; |
| while (off < arr.Length && lenToRead > 0) |
| { |
| int read = buf.Get(off, target, off, lenToRead); |
| Assert.IsTrue(read > 0); |
| Assert.IsTrue(read <= lenToRead); |
| lenToRead -= read; |
| off += read; |
| } |
| |
| for (int j = 0; j < lenToCheck; j++) |
| { |
| Assert.AreEqual(arr[j + i], target[j + i]); |
| } |
| } |
| |
| long expectedBytesUsed = RamUsageEstimator.SizeOf(buf); |
| long computedBytesUsed = buf.RamBytesUsed(); |
| Assert.AreEqual(expectedBytesUsed, computedBytesUsed); |
| } |
| } |
| } |
| |
| [Test] |
| public virtual void TestPackedInputOutput() |
| { |
| long[] longs = new long[Random.Next(8192)]; |
| int[] bitsPerValues = new int[longs.Length]; |
| bool[] skip = new bool[longs.Length]; |
| for (int i = 0; i < longs.Length; ++i) |
| { |
| int bpv = RandomInts.RandomInt32Between(Random, 1, 64); |
| bitsPerValues[i] = Random.NextBoolean() ? bpv : TestUtil.NextInt32(Random, bpv, 64); |
| if (bpv == 64) |
| { |
| longs[i] = Random.NextInt64(); |
| } |
| else |
| { |
| longs[i] = TestUtil.NextInt64(Random, 0, PackedInt32s.MaxValue(bpv)); |
| } |
| skip[i] = Rarely(); |
| } |
| |
| Directory dir = NewDirectory(); |
| IndexOutput @out = dir.CreateOutput("out.bin", IOContext.DEFAULT); |
| PackedDataOutput pout = new PackedDataOutput(@out); |
| long totalBits = 0; |
| for (int i = 0; i < longs.Length; ++i) |
| { |
| pout.WriteInt64(longs[i], bitsPerValues[i]); |
| totalBits += bitsPerValues[i]; |
| if (skip[i]) |
| { |
| pout.Flush(); |
| totalBits = 8 * (long)Math.Ceiling((double)totalBits / 8); |
| } |
| } |
| pout.Flush(); |
| Assert.AreEqual((long)Math.Ceiling((double)totalBits / 8), @out.GetFilePointer()); |
| @out.Dispose(); |
| IndexInput @in = dir.OpenInput("out.bin", IOContext.READ_ONCE); |
| PackedDataInput pin = new PackedDataInput(@in); |
| for (int i = 0; i < longs.Length; ++i) |
| { |
| Assert.AreEqual(longs[i], pin.ReadInt64(bitsPerValues[i]), "" + i); |
| if (skip[i]) |
| { |
| pin.SkipToNextByte(); |
| } |
| } |
| assertEquals((long)Math.Ceiling((double)totalBits / 8), @in.GetFilePointer()); |
| @in.Dispose(); |
| dir.Dispose(); |
| } |
| |
| [Test] |
| public virtual void TestBlockPackedReaderWriter() |
| { |
| int iters = AtLeast(2); |
| for (int iter = 0; iter < iters; ++iter) |
| { |
| int blockSize = 1 << TestUtil.NextInt32(Random, 6, 18); |
| int valueCount = Random.Next(1 << 18); |
| long[] values = new long[valueCount]; |
| long minValue = 0; |
| int bpv = 0; |
| for (int i = 0; i < valueCount; ++i) |
| { |
| if (i % blockSize == 0) |
| { |
| minValue = Rarely() ? Random.Next(256) : Rarely() ? -5 : Random.NextInt64(); |
| bpv = Random.Next(65); |
| } |
| if (bpv == 0) |
| { |
| values[i] = minValue; |
| } |
| else if (bpv == 64) |
| { |
| values[i] = Random.NextInt64(); |
| } |
| else |
| { |
| values[i] = minValue + TestUtil.NextInt64(Random, 0, (1L << bpv) - 1); |
| } |
| } |
| |
| Directory dir = NewDirectory(); |
| IndexOutput @out = dir.CreateOutput("out.bin", IOContext.DEFAULT); |
| BlockPackedWriter writer = new BlockPackedWriter(@out, blockSize); |
| for (int i = 0; i < valueCount; ++i) |
| { |
| Assert.AreEqual(i, writer.Ord); |
| writer.Add(values[i]); |
| } |
| Assert.AreEqual(valueCount, writer.Ord); |
| writer.Finish(); |
| Assert.AreEqual(valueCount, writer.Ord); |
| long fp = @out.GetFilePointer(); |
| @out.Dispose(); |
| |
| IndexInput in1 = dir.OpenInput("out.bin", IOContext.DEFAULT); |
| byte[] buf = new byte[(int)fp]; |
| in1.ReadBytes(buf, 0, (int)fp); |
| in1.Seek(0L); |
| ByteArrayDataInput in2 = new ByteArrayDataInput(buf); |
| DataInput @in = Random.NextBoolean() ? (DataInput)in1 : in2; |
| BlockPackedReaderIterator it = new BlockPackedReaderIterator(@in, PackedInt32s.VERSION_CURRENT, blockSize, valueCount); |
| for (int i = 0; i < valueCount; ) |
| { |
| if (Random.NextBoolean()) |
| { |
| Assert.AreEqual(values[i], it.Next(), "" + i); |
| ++i; |
| } |
| else |
| { |
| Int64sRef nextValues = it.Next(TestUtil.NextInt32(Random, 1, 1024)); |
| for (int j = 0; j < nextValues.Length; ++j) |
| { |
| Assert.AreEqual(values[i + j], nextValues.Int64s[nextValues.Offset + j], "" + (i + j)); |
| } |
| i += nextValues.Length; |
| } |
| Assert.AreEqual(i, it.Ord); |
| } |
| assertEquals(fp, @in is ByteArrayDataInput ? ((ByteArrayDataInput)@in).Position : ((IndexInput)@in).GetFilePointer()); |
| try |
| { |
| it.Next(); |
| Assert.IsTrue(false); |
| } |
| #pragma warning disable 168 |
| catch (IOException e) |
| #pragma warning restore 168 |
| { |
| // OK |
| } |
| |
| if (@in is ByteArrayDataInput) |
| { |
| ((ByteArrayDataInput)@in).Position = 0; |
| } |
| else |
| { |
| ((IndexInput)@in).Seek(0L); |
| } |
| BlockPackedReaderIterator it2 = new BlockPackedReaderIterator(@in, PackedInt32s.VERSION_CURRENT, blockSize, valueCount); |
| int k = 0; |
| while (true) |
| { |
| int skip = TestUtil.NextInt32(Random, 0, valueCount - k); |
| it2.Skip(skip); |
| k += skip; |
| Assert.AreEqual(k, it2.Ord); |
| if (k == valueCount) |
| { |
| break; |
| } |
| else |
| { |
| Assert.AreEqual(values[k], it2.Next()); |
| ++k; |
| } |
| } |
| assertEquals(fp, @in is ByteArrayDataInput ? ((ByteArrayDataInput)@in).Position : (((IndexInput)@in).GetFilePointer())); |
| try |
| { |
| it2.Skip(1); |
| Assert.IsTrue(false); |
| } |
| #pragma warning disable 168 |
| catch (IOException e) |
| #pragma warning restore 168 |
| { |
| // OK |
| } |
| |
| in1.Seek(0L); |
| BlockPackedReader reader = new BlockPackedReader(in1, PackedInt32s.VERSION_CURRENT, blockSize, valueCount, Random.NextBoolean()); |
| assertEquals(in1.GetFilePointer(), in1.Length); |
| for (k = 0; k < valueCount; ++k) |
| { |
| Assert.AreEqual(values[k], reader.Get(k), "i=" + k); |
| } |
| in1.Dispose(); |
| dir.Dispose(); |
| } |
| } |
| |
| [Test] |
| public virtual void TestMonotonicBlockPackedReaderWriter() |
| { |
| int iters = AtLeast(2); |
| for (int iter = 0; iter < iters; ++iter) |
| { |
| int blockSize = 1 << TestUtil.NextInt32(Random, 6, 18); |
| int valueCount = Random.Next(1 << 18); |
| long[] values = new long[valueCount]; |
| if (valueCount > 0) |
| { |
| values[0] = Random.NextBoolean() ? Random.Next(10) : Random.Next(int.MaxValue); |
| int maxDelta = Random.Next(64); |
| for (int i = 1; i < valueCount; ++i) |
| { |
| if (Random.NextDouble() < 0.1d) |
| { |
| maxDelta = Random.Next(64); |
| } |
| values[i] = Math.Max(0, values[i - 1] + TestUtil.NextInt32(Random, -16, maxDelta)); |
| } |
| } |
| |
| Directory dir = NewDirectory(); |
| IndexOutput @out = dir.CreateOutput("out.bin", IOContext.DEFAULT); |
| MonotonicBlockPackedWriter writer = new MonotonicBlockPackedWriter(@out, blockSize); |
| for (int i = 0; i < valueCount; ++i) |
| { |
| Assert.AreEqual(i, writer.Ord); |
| writer.Add(values[i]); |
| } |
| Assert.AreEqual(valueCount, writer.Ord); |
| writer.Finish(); |
| Assert.AreEqual(valueCount, writer.Ord); |
| long fp = @out.GetFilePointer(); |
| @out.Dispose(); |
| |
| IndexInput @in = dir.OpenInput("out.bin", IOContext.DEFAULT); |
| MonotonicBlockPackedReader reader = new MonotonicBlockPackedReader(@in, PackedInt32s.VERSION_CURRENT, blockSize, valueCount, Random.NextBoolean()); |
| assertEquals(fp, @in.GetFilePointer()); |
| for (int i = 0; i < valueCount; ++i) |
| { |
| Assert.AreEqual(values[i], reader.Get(i),"i=" + i); |
| } |
| @in.Dispose(); |
| dir.Dispose(); |
| } |
| } |
| |
| [Test] |
| [Nightly] |
| public virtual void TestBlockReaderOverflow() |
| { |
| long valueCount = TestUtil.NextInt64(Random, 1L + int.MaxValue, (long)int.MaxValue * 2); |
| int blockSize = 1 << TestUtil.NextInt32(Random, 20, 22); |
| Directory dir = NewDirectory(); |
| IndexOutput @out = dir.CreateOutput("out.bin", IOContext.DEFAULT); |
| BlockPackedWriter writer = new BlockPackedWriter(@out, blockSize); |
| long value = Random.Next() & 0xFFFFFFFFL; |
| long valueOffset = TestUtil.NextInt64(Random, 0, valueCount - 1); |
| for (long i = 0; i < valueCount; ) |
| { |
| Assert.AreEqual(i, writer.Ord); |
| if ((i & (blockSize - 1)) == 0 && (i + blockSize < valueOffset || i > valueOffset && i + blockSize < valueCount)) |
| { |
| writer.AddBlockOfZeros(); |
| i += blockSize; |
| } |
| else if (i == valueOffset) |
| { |
| writer.Add(value); |
| ++i; |
| } |
| else |
| { |
| writer.Add(0); |
| ++i; |
| } |
| } |
| writer.Finish(); |
| @out.Dispose(); |
| IndexInput @in = dir.OpenInput("out.bin", IOContext.DEFAULT); |
| BlockPackedReaderIterator it = new BlockPackedReaderIterator(@in, PackedInt32s.VERSION_CURRENT, blockSize, valueCount); |
| it.Skip(valueOffset); |
| Assert.AreEqual(value, it.Next()); |
| @in.Seek(0L); |
| BlockPackedReader reader = new BlockPackedReader(@in, PackedInt32s.VERSION_CURRENT, blockSize, valueCount, Random.NextBoolean()); |
| Assert.AreEqual(value, reader.Get(valueOffset)); |
| for (int i = 0; i < 5; ++i) |
| { |
| long offset = TestUtil.NextInt64(Random, 0, valueCount - 1); |
| if (offset == valueOffset) |
| { |
| Assert.AreEqual(value, reader.Get(offset)); |
| } |
| else |
| { |
| Assert.AreEqual(0, reader.Get(offset)); |
| } |
| } |
| @in.Dispose(); |
| dir.Dispose(); |
| } |
| |
| } |
| |
| } |