diff --git a/community/pom.xml b/community/pom.xml index cb9a661f770e2..b675b8a01b154 100644 --- a/community/pom.xml +++ b/community/pom.xml @@ -58,6 +58,7 @@ dbms command-line procedure-compiler + random-values values ssl spatial-index diff --git a/community/random-values/src/main/java/org/neo4j/values/RandomValue.java b/community/random-values/src/main/java/org/neo4j/values/RandomValue.java new file mode 100644 index 0000000000000..26591da64e5cc --- /dev/null +++ b/community/random-values/src/main/java/org/neo4j/values/RandomValue.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.values; + +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; + +import org.neo4j.values.storable.BooleanValue; +import org.neo4j.values.storable.ByteValue; +import org.neo4j.values.storable.DoubleValue; +import org.neo4j.values.storable.FloatValue; +import org.neo4j.values.storable.IntValue; +import org.neo4j.values.storable.LongValue; +import org.neo4j.values.storable.NumberValue; +import org.neo4j.values.storable.ShortValue; +import org.neo4j.values.storable.Values; + +import static java.lang.Math.abs; +import static org.neo4j.values.storable.Values.byteValue; +import static org.neo4j.values.storable.Values.doubleValue; +import static org.neo4j.values.storable.Values.floatValue; +import static org.neo4j.values.storable.Values.intValue; +import static org.neo4j.values.storable.Values.longValue; +import static org.neo4j.values.storable.Values.shortValue; + +public class RandomValue +{ + //TODO make possible to use SplittableRandom + private final Random random; + + public RandomValue() + { + this( ThreadLocalRandom.current() ); + } + + public RandomValue( Random random ) + { + this.random = random; + } + + LongValue nextLongValue() + { + return longValue( random.nextLong() ); + } + + LongValue nextLongValue( long bound ) + { + return longValue( nextLong( bound ) ); + } + + public LongValue nextLongValue( long lower, long upper ) + { + return longValue( nextLong( (upper - lower) + 1L ) + lower ); + } + + public BooleanValue nextBooleanValue() + { + return Values.booleanValue( random.nextBoolean() ); + } + + public IntValue nextIntValue( int bound ) + { + return intValue( random.nextInt( bound ) ); + } + + public IntValue nextIntValue() + { + return intValue( random.nextInt() ); + } + + public ShortValue nextShortValue( short bound ) + { + return shortValue( (short) random.nextInt( bound ) ); + } + + public ShortValue nextShortValue() + { + return shortValue( (short) random.nextInt() ); + } + + public ByteValue nextByteValue( byte bound ) + { + return byteValue( (byte) random.nextInt( bound ) ); + } + + public ByteValue nextByteValue() + { + return byteValue( (byte) random.nextInt() ); + } + + public FloatValue nextFloatValue() + { + return floatValue( random.nextFloat() ); + } + + public DoubleValue nextDoubleValue() + { + return doubleValue( random.nextFloat() ); + } + + public NumberValue nextNumberValue() + { + int type = random.nextInt( 6 ); + switch ( type ) + { + case 0: + return nextByteValue(); + case 1: + return nextShortValue(); + case 2: + return nextIntValue(); + case 3: + return nextLongValue(); + case 4: + return nextFloatValue(); + case 5: + return nextDoubleValue(); + default: + throw new IllegalArgumentException( "Unknown value type " + type ); + } + } + + private long nextLong( long bound ) + { + return abs( random.nextLong() ) % bound; + } +} diff --git a/community/random-values/src/test/java/org/neo4j/values/RandomValueTest.java b/community/random-values/src/test/java/org/neo4j/values/RandomValueTest.java new file mode 100644 index 0000000000000..105bc4eb0eae3 --- /dev/null +++ b/community/random-values/src/test/java/org/neo4j/values/RandomValueTest.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.values; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.function.Supplier; + +import org.neo4j.values.storable.ByteValue; +import org.neo4j.values.storable.DoubleValue; +import org.neo4j.values.storable.FloatValue; +import org.neo4j.values.storable.IntValue; +import org.neo4j.values.storable.LongValue; +import org.neo4j.values.storable.NumberValue; +import org.neo4j.values.storable.ShortValue; +import org.neo4j.values.storable.Value; + +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.lessThan; +import static org.hamcrest.Matchers.lessThanOrEqualTo; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertThat; +import static org.neo4j.values.storable.Values.ZERO_INT; +import static org.neo4j.values.storable.Values.longValue; + +public class RandomValueTest +{ + private static final int ITERATIONS = 100; + private final RandomValue randomValue = new RandomValue(); + private final static byte BOUND = 100; + private final static LongValue UPPER = longValue( BOUND ); + private static final Set> NUMBER_TYPES = new HashSet<>( Arrays.asList( + LongValue.class, IntValue.class, ShortValue.class, ByteValue.class, FloatValue.class, + DoubleValue.class ) ); + + @Test + public void nextLongValueUnbounded() + { + checkDistribution( randomValue::nextLongValue ); + } + + @Test + public void nextLongValueBounded() + { + checkDistribution( () -> randomValue.nextLongValue( BOUND ) ); + checkBounded( () -> randomValue.nextLongValue( BOUND ) ); + } + + @Test + public void nextLongValueBoundedAndShifted() + { + Set values = new HashSet<>(); + for ( int i = 0; i < ITERATIONS; i++ ) + { + LongValue value = randomValue.nextLongValue( 1337, 1337 + BOUND ); + assertThat( value, notNullValue() ); + assertThat( value.compareTo( longValue( 1337 ) ), greaterThanOrEqualTo( 0 ) ); + assertThat( value.toString(), value.compareTo( longValue( 1337 + BOUND ) ), lessThanOrEqualTo( 0 ) ); + values.add( value ); + } + + assertThat( values.size(), greaterThan( 1 ) ); + } + + @Test + public void nextBooleanValue() + { + checkDistribution( randomValue::nextBooleanValue ); + } + + @Test + public void nextIntValueUnbounded() + { + checkDistribution( randomValue::nextIntValue ); + } + + @Test + public void nextIntValueBounded() + { + checkDistribution( () -> randomValue.nextIntValue( BOUND ) ); + checkBounded( () -> randomValue.nextIntValue( BOUND ) ); + } + + @Test + public void nextShortValueUnbounded() + { + checkDistribution( randomValue::nextShortValue ); + } + + @Test + public void nextShortValueBounded() + { + checkDistribution( () -> randomValue.nextShortValue( BOUND ) ); + checkBounded( () -> randomValue.nextShortValue( BOUND ) ); + } + + + @Test + public void nextByteValueUnbounded() + { + checkDistribution( randomValue::nextByteValue ); + } + + @Test + public void nextByteValueBounded() + { + checkDistribution( () -> randomValue.nextByteValue( BOUND ) ); + checkBounded( () -> randomValue.nextByteValue( BOUND ) ); + } + + @Test + public void nextFloatValue() + { + checkDistribution( randomValue::nextFloatValue ); + } + + @Test + public void nextDoubleValue() + { + checkDistribution( randomValue::nextDoubleValue ); + } + + @Test + public void nextNumberValue() + { + HashSet> seen = new HashSet<>( NUMBER_TYPES ); + + for ( int i = 0; i < ITERATIONS; i++ ) + { + NumberValue numberValue = randomValue.nextNumberValue(); + assertThat( NUMBER_TYPES, hasItem( numberValue.getClass() )); + seen.remove( numberValue.getClass() ); + } + assertThat( seen, empty() ); + } + + private void checkDistribution( Supplier supplier ) + { + Set values = new HashSet<>(); + for ( int i = 0; i < ITERATIONS; i++ ) + { + Value value = supplier.get(); + assertThat( value, notNullValue() ); + values.add( value ); + } + + assertThat( values.size(), greaterThan( 1 ) ); + } + + private void checkBounded( Supplier supplier ) + { + for ( int i = 0; i < ITERATIONS; i++ ) + { + NumberValue value = supplier.get(); + assertThat( value, notNullValue() ); + assertThat( value.compareTo( ZERO_INT ), greaterThanOrEqualTo( 0 ) ); + assertThat( value.compareTo( UPPER ), lessThan( 0 ) ); + } + } +} \ No newline at end of file diff --git a/community/values/src/main/java/org/neo4j/values/storable/NumberValue.java b/community/values/src/main/java/org/neo4j/values/storable/NumberValue.java index d58548193d5b6..c2986d1ac96d8 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/NumberValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/NumberValue.java @@ -45,9 +45,9 @@ public static double safeCastFloatingPoint( String name, AnyValue value, double public abstract long longValue(); - abstract int compareTo( IntegralValue other ); + public abstract int compareTo( IntegralValue other ); - abstract int compareTo( FloatingPointValue other ); + public abstract int compareTo( FloatingPointValue other ); @Override int unsafeCompareTo( Value otherValue )