Skip to content

Commit

Permalink
Add random generation of NumberValues and BooleanValue
Browse files Browse the repository at this point in the history
  • Loading branch information
pontusmelke committed May 11, 2018
1 parent e21864c commit ba971a8
Show file tree
Hide file tree
Showing 4 changed files with 330 additions and 2 deletions.
1 change: 1 addition & 0 deletions community/pom.xml
Expand Up @@ -58,6 +58,7 @@
<module>dbms</module>
<module>command-line</module>
<module>procedure-compiler</module>
<module>random-values</module>
<module>values</module>
<module>ssl</module>
<module>spatial-index</module>
Expand Down
@@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}
@@ -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 <http://www.gnu.org/licenses/>.
*/
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<Class<? extends NumberValue>> 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<Value> 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<Class<? extends NumberValue>> 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<Value> supplier )
{
Set<Value> 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<NumberValue> 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 ) );
}
}
}
Expand Up @@ -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 )
Expand Down

0 comments on commit ba971a8

Please sign in to comment.