blob: 09a536274ddbfc41273f698cde58b061ac36e2e3 [file]
/*
* 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.
*/
package org.apache.datasketches.theta;
import static java.lang.foreign.ValueLayout.JAVA_BYTE;
import static java.lang.foreign.ValueLayout.JAVA_LONG_UNALIGNED;
import static org.apache.datasketches.hash.MurmurHash3.hash;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import java.lang.foreign.MemorySegment;
import org.apache.datasketches.common.SketchesArgumentException;
import org.apache.datasketches.common.Util;
import org.testng.annotations.Test;
/**
* @author Lee Rhodes
*/
public class SingleItemSketchTest {
final static short DEFAULT_SEED_HASH = (short) (Util.computeSeedHash(Util.DEFAULT_UPDATE_SEED) & 0XFFFFL);
@Test
public void check1() {
final ThetaUnion union = ThetaSetOperation.builder().buildUnion();
union.union(SingleItemSketch.create(1));
union.union(SingleItemSketch.create(1.0));
union.union(SingleItemSketch.create(0.0));
union.union(SingleItemSketch.create("1"));
union.union(SingleItemSketch.create(new byte[] {1,2,3,4}));
union.union(SingleItemSketch.create(new char[] {'a'}));
union.union(SingleItemSketch.create(new int[] {2}));
union.union(SingleItemSketch.create(new long[] {3}));
union.union(SingleItemSketch.create(-0.0)); //duplicate
final double est = union.getResult().getEstimate();
println(""+est);
assertEquals(est, 8.0, 0.0);
assertNull(SingleItemSketch.create(""));
final String str = null;
assertNull(SingleItemSketch.create(str));//returns null
assertNull(SingleItemSketch.create(new byte[0]));//returns null
final byte[] byteArr = null;
assertNull(SingleItemSketch.create(byteArr));//returns null
assertNull(SingleItemSketch.create(new char[0]));//returns null
final char[] charArr = null;
assertNull(SingleItemSketch.create(charArr));//returns null
assertNull(SingleItemSketch.create(new int[0]));//returns null
final int[] intArr = null;
assertNull(SingleItemSketch.create(intArr));//returns null
assertNull(SingleItemSketch.create(new long[0]));//returns null
final long[] longArr = null;
assertNull(SingleItemSketch.create(longArr));//returns null
}
@Test
public void check2() {
final long seed = Util.DEFAULT_UPDATE_SEED;
final ThetaUnion union = ThetaSetOperation.builder().buildUnion();
union.union(SingleItemSketch.create(1, seed));
union.union(SingleItemSketch.create(1.0, seed));
union.union(SingleItemSketch.create(0.0, seed));
union.union(SingleItemSketch.create("1", seed));
union.union(SingleItemSketch.create(new byte[] {1,2,3,4}, seed));
union.union(SingleItemSketch.create(new char[] {'a'}, seed));
union.union(SingleItemSketch.create(new int[] {2}, seed));
union.union(SingleItemSketch.create(new long[] {3}, seed));
union.union(SingleItemSketch.create(-0.0, seed)); //duplicate
final double est = union.getResult().getEstimate();
println(""+est);
assertEquals(est, 8.0, 0.0);
assertNull(SingleItemSketch.create("", seed));
final String str = null;
assertNull(SingleItemSketch.create(str, seed));//returns null
assertNull(SingleItemSketch.create(new byte[0], seed));//returns null
final byte[] byteArr = null;
assertNull(SingleItemSketch.create(byteArr, seed));//returns null
assertNull(SingleItemSketch.create(new char[0], seed));//returns null
final char[] charArr = null;
assertNull(SingleItemSketch.create(charArr, seed));//returns null
assertNull(SingleItemSketch.create(new int[0], seed));//returns null
final int[] intArr = null;
assertNull(SingleItemSketch.create(intArr, seed));//returns null
assertNull(SingleItemSketch.create(new long[0], seed));//returns null
final long[] longArr = null;
assertNull(SingleItemSketch.create(longArr, seed));//returns null
}
@Test
public void checkSketchInterface() {
final SingleItemSketch sis = SingleItemSketch.create(1);
assertEquals(sis.getCompactBytes(), 16);
assertEquals(sis.getEstimate(), 1.0);
assertEquals(sis.getLowerBound(1), 1.0);
assertEquals(sis.getRetainedEntries(true), 1);
assertEquals(sis.getUpperBound(1), 1.0);
assertFalse(sis.isOffHeap());
assertFalse(sis.hasMemorySegment());
assertFalse(sis.isEmpty());
assertTrue(sis.isOrdered());
}
@Test
public void checkLessThanThetaLong() {
for (int i = 0; i < 10; i++) {
final long[] data = { i };
final long h = hash(data, Util.DEFAULT_UPDATE_SEED)[0] >>> 1;
final SingleItemSketch sis = SingleItemSketch.create(i);
final long halfMax = Long.MAX_VALUE >> 1;
final int count = sis.getCountLessThanThetaLong(halfMax);
assertEquals(count, (h < halfMax) ? 1 : 0);
}
}
@Test
public void checkSerDe() {
final SingleItemSketch sis = SingleItemSketch.create(1);
final byte[] byteArr = sis.toByteArray();
final MemorySegment seg = MemorySegment.ofArray(byteArr);
final short defaultSeedHash = Util.computeSeedHash(Util.DEFAULT_UPDATE_SEED);
final SingleItemSketch sis2 = SingleItemSketch.heapify(seg, defaultSeedHash);
assertEquals(sis2.getEstimate(), 1.0);
final SingleItemSketch sis3 = SingleItemSketch.heapify(seg , defaultSeedHash);
assertEquals(sis3.getEstimate(), 1.0);
final ThetaUnion union = ThetaSetOperation.builder().buildUnion();
union.union(sis);
union.union(sis2);
union.union(sis3);
final CompactThetaSketch csk = union.getResult();
assertTrue(csk instanceof SingleItemSketch);
assertEquals(union.getResult().getEstimate(), 1.0);
}
@Test
public void checkRestricted() {
final SingleItemSketch sis = SingleItemSketch.create(1);
assertNull(sis.getMemorySegment());
assertEquals(sis.getCompactPreambleLongs(), 1);
}
@Test
public void unionWrapped() {
final ThetaSketch sketch = SingleItemSketch.create(1);
final ThetaUnion union = ThetaSetOperation.builder().buildUnion();
final MemorySegment seg = MemorySegment.ofArray(sketch.toByteArray());
union.union(seg );
assertEquals(union.getResult().getEstimate(), 1, 0);
}
@Test
public void buildAndCompact() {
UpdatableThetaSketch sk1;
CompactThetaSketch csk;
int bytes;
//On-heap
sk1 = UpdatableThetaSketch.builder().setNominalEntries(32).build();
sk1.update(1);
csk = sk1.compact(true, null);
assertTrue(csk instanceof SingleItemSketch);
csk = sk1.compact(false, null);
assertTrue(csk instanceof SingleItemSketch);
//Off-heap
bytes = ThetaSketch.getMaxUpdateSketchBytes(32);
MemorySegment wseg = MemorySegment.ofArray(new byte[bytes]);
sk1= UpdatableThetaSketch.builder().setNominalEntries(32).build(wseg );
sk1.update(1);
csk = sk1.compact(true, null);
assertTrue(csk instanceof SingleItemSketch);
csk = sk1.compact(false, null);
assertTrue(csk instanceof SingleItemSketch);
bytes = ThetaSketch.getMaxCompactSketchBytes(1);
wseg = MemorySegment.ofArray(new byte[bytes]);
csk = sk1.compact(true, wseg );
assertTrue(csk.isOrdered());
csk = sk1.compact(false, wseg );
assertTrue(csk.isOrdered());
}
@Test
public void intersection() {
UpdatableThetaSketch sk1, sk2;
CompactThetaSketch csk;
int bytes;
//ThetaIntersection on-heap
sk1 = UpdatableThetaSketch.builder().setNominalEntries(32).build();
sk2 = UpdatableThetaSketch.builder().setNominalEntries(32).build();
sk1.update(1);
sk1.update(2);
sk2.update(1);
ThetaIntersection inter = ThetaSetOperation.builder().buildIntersection();
inter.intersect(sk1);
inter.intersect(sk2);
csk = inter.getResult(true, null);
assertTrue(csk instanceof SingleItemSketch);
//ThetaIntersection off-heap
bytes = ThetaSetOperation.getMaxIntersectionBytes(32);
final MemorySegment wseg = MemorySegment.ofArray(new byte[bytes]);
inter = ThetaSetOperation.builder().buildIntersection(wseg );
inter.intersect(sk1);
inter.intersect(sk2);
csk = inter.getResult(true, null);
assertTrue(csk instanceof SingleItemSketch);
csk = inter.getResult(false, null);
assertTrue(csk instanceof SingleItemSketch);
}
@Test
public void union() {
UpdatableThetaSketch sk1, sk2;
CompactThetaSketch csk;
int bytes;
//ThetaUnion on-heap
sk1 = UpdatableThetaSketch.builder().setNominalEntries(32).build();
sk2 = UpdatableThetaSketch.builder().setNominalEntries(32).build();
sk1.update(1);
sk2.update(1);
ThetaUnion union = ThetaSetOperation.builder().buildUnion();
union.union(sk1);
union.union(sk2);
csk = union.getResult(true, null);
assertTrue(csk instanceof SingleItemSketch);
//ThetaUnion off-heap
bytes = ThetaSetOperation.getMaxUnionBytes(32);
final MemorySegment wseg = MemorySegment.ofArray(new byte[bytes]);
union = ThetaSetOperation.builder().buildUnion(wseg );
union.union(sk1);
union.union(sk2);
csk = union.getResult(true, null);
assertTrue(csk instanceof SingleItemSketch);
csk = union.getResult(false, null);
assertTrue(csk instanceof SingleItemSketch);
}
@Test
public void aNotB() {
UpdatableThetaSketch sk1, sk2;
CompactThetaSketch csk;
//ThetaAnotB on-heap
sk1 = UpdatableThetaSketch.builder().setNominalEntries(32).build();
sk2 = UpdatableThetaSketch.builder().setNominalEntries(32).build();
sk1.update(1);
sk2.update(2);
final ThetaAnotB aNotB = ThetaSetOperation.builder().buildANotB();
aNotB.setA(sk1);
aNotB.notB(sk2);
csk = aNotB.getResult(true, null, true);
assertTrue(csk instanceof SingleItemSketch);
//not ThetaAnotB off-heap form
}
@Test
public void checkHeapifyInstance() {
final UpdatableThetaSketch sk1 = new UpdatableThetaSketchBuilder().build();
sk1.update(1);
final UpdatableThetaSketch sk2 = new UpdatableThetaSketchBuilder().build();
sk2.update(1);
final ThetaIntersection inter = ThetaSetOperation.builder().buildIntersection();
inter.intersect(sk1);
inter.intersect(sk2);
final MemorySegment wseg = MemorySegment.ofArray(new byte[16]);
final CompactThetaSketch csk = inter.getResult(false, wseg );
assertTrue(csk.isOrdered());
final ThetaSketch csk2 = ThetaSketch.heapify(wseg );
assertTrue(csk2 instanceof SingleItemSketch);
println(csk2.toString(true, true, 1, true));
}
@Test
public void checkSingleItemBadFlags() {
final short defaultSeedHash = Util.computeSeedHash(Util.DEFAULT_UPDATE_SEED);
final UpdatableThetaSketch sk1 = new UpdatableThetaSketchBuilder().build();
sk1.update(1);
final MemorySegment wseg = MemorySegment.ofArray(new byte[16]);
sk1.compact(true, wseg );
wseg .set(JAVA_BYTE, 5, (byte) 0); //corrupt flags to zero
try {
SingleItemSketch.heapify(wseg , defaultSeedHash); //fails due to corrupted flags bytes
fail();
} catch (final SketchesArgumentException e) { }
}
@Test
public void checkDirectUnionSingleItem2() {
ThetaSketch sk = ThetaSketch.wrap(siSkWoutSiFlag24Bytes());
assertEquals(sk.getEstimate(), 1.0, 0.0);
//println(sk.toString());
sk = ThetaSketch.wrap(siSkWithSiFlag24Bytes());
assertEquals(sk.getEstimate(), 1.0, 0.0);
//println(sk.toString());
}
@Test
public void checkSingleItemCompact() {
final UpdatableThetaSketch sk1 = new UpdatableThetaSketchBuilder().build();
sk1.update(1);
final CompactThetaSketch csk = sk1.compact();
assertTrue(csk instanceof SingleItemSketch);
final CompactThetaSketch csk2 = csk.compact();
assertEquals(csk, csk2);
final CompactThetaSketch csk3 = csk.compact(true, MemorySegment.ofArray(new byte[16]));
assertTrue(csk3 instanceof DirectCompactSketch);
assertEquals(csk2.getCurrentPreambleLongs(), 1);
assertEquals(csk3.getCurrentPreambleLongs(), 1);
}
static final long SiSkPre0WithSiFlag = 0x93cc3a0000030301L;
static final long SiSkPre0WoutSiFlag = 0x93cc1a0000030301L;
static final long Hash = 0x05a186bdcb7df915L;
static MemorySegment siSkWithSiFlag24Bytes() {
final int cap = 24; //8 extra bytes
final MemorySegment wseg = MemorySegment.ofArray(new byte[cap]);
wseg .set(JAVA_LONG_UNALIGNED, 0, SiSkPre0WithSiFlag);
wseg .set(JAVA_LONG_UNALIGNED, 8, Hash);
return wseg ;
}
static MemorySegment siSkWoutSiFlag24Bytes() {
final int cap = 24; //8 extra bytes
final MemorySegment wseg = MemorySegment.ofArray(new byte[cap]);
wseg .set(JAVA_LONG_UNALIGNED, 0, SiSkPre0WoutSiFlag);
wseg .set(JAVA_LONG_UNALIGNED, 8, Hash);
return wseg;
}
@Test
public void printlnTest() {
println("PRINTING: "+this.getClass().getName());
}
/**
* @param s value to print
*/
static void println(final String s) {
//System.out.println(s); //disable here
}
}