Skip to content

Commit

Permalink
Merge pull request #7600 from lutovich/2.3-reuse-node-ids
Browse files Browse the repository at this point in the history
Added tests for node id reuse
  • Loading branch information
tinwelint committed Jul 26, 2016
2 parents 868b4d7 + 05faf2c commit 37e1daa
Show file tree
Hide file tree
Showing 8 changed files with 463 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -319,30 +319,7 @@ public String toString()
}
};

public static final Function<String, List<String>> STRING_LIST = new Function<String, List<String>>()
{
@Override
public List<String> apply( String value )
{
String[] list = value.split( SEPARATOR );
List<String> result = new ArrayList();
for( String item : list)
{
item = item.trim();
if( StringUtils.isNotEmpty( item ) )
{
result.add( item );
}
}
return result;
}

@Override
public String toString()
{
return "a comma-seperated string";
}
};
public static final Function<String,List<String>> STRING_LIST = list( SEPARATOR, STRING );

public static final Function<String,HostnamePort> HOSTNAME_PORT = new Function<String, HostnamePort>()
{
Expand Down Expand Up @@ -509,17 +486,22 @@ public Long apply( String from )
}
};

public static <T extends Enum> Function<String, T> options( final Class<T> enumClass )
public static <T extends Enum<T>> Function<String, T> options( final Class<T> enumClass )
{
return options( EnumSet.allOf( enumClass ) );
return options( EnumSet.allOf( enumClass ), false );
}

public static <T> Function<String, T> options( T... optionValues )
{
return Settings.<T>options( Iterables.<T,T>iterable( optionValues ) );
return options( Iterables.<T,T>iterable( optionValues ), false );
}

public static <T> Function<String, T> options( final Iterable<T> optionValues )
public static <T> Function<String, T> optionsIgnoreCase( T... optionValues )
{
return options( Iterables.<T,T>iterable( optionValues ), true );
}

public static <T> Function<String, T> options( final Iterable<T> optionValues, final boolean ignoreCase )
{
return new Function<String, T>()
{
Expand All @@ -528,12 +510,16 @@ public T apply( String value )
{
for ( T optionValue : optionValues )
{
if ( optionValue.toString().equals( value ) )
String allowedValue = optionValue.toString();

if ( allowedValue.equals( value ) || (ignoreCase && allowedValue.equalsIgnoreCase( value )) )
{
return optionValue;
}
}
throw new IllegalArgumentException( "must be one of " + Iterables.toList( optionValues ).toString() );
String possibleValues = Iterables.toList( optionValues ).toString();
throw new IllegalArgumentException(
"must be one of " + possibleValues + " case " + (ignoreCase ? "insensitive" : "sensitive") );
}

@Override
Expand All @@ -560,11 +546,12 @@ public static <T> Function<String, List<T>> list( final String separator, final
@Override
public List<T> apply( String value )
{
List<T> list = new ArrayList<T>();
if ( value.length() > 0 )
List<T> list = new ArrayList<>();
String[] parts = value.split( separator );
for ( String part : parts )
{
String[] parts = value.split( separator );
for ( String part : parts )
part = part.trim();
if ( StringUtils.isNotEmpty( part ) )
{
list.add( itemParser.apply( part ) );
}
Expand Down
25 changes: 23 additions & 2 deletions community/kernel/src/test/java/org/neo4j/helpers/SettingsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

import java.io.File;
import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.neo4j.graphdb.config.InvalidSettingException;
Expand All @@ -34,15 +36,16 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;

import static org.neo4j.helpers.Functions.map;
import static org.neo4j.helpers.collection.MapUtil.stringMap;
import static org.neo4j.kernel.configuration.Settings.DURATION;
import static org.neo4j.kernel.configuration.Settings.INTEGER;
import static org.neo4j.kernel.configuration.Settings.MANDATORY;
import static org.neo4j.kernel.configuration.Settings.NORMALIZED_RELATIVE_URI;
import static org.neo4j.kernel.configuration.Settings.NO_DEFAULT;
import static org.neo4j.kernel.configuration.Settings.PATH;
import static org.neo4j.kernel.configuration.Settings.STRING;
import static org.neo4j.kernel.configuration.Settings.STRING_LIST;
import static org.neo4j.kernel.configuration.Settings.basePath;
import static org.neo4j.kernel.configuration.Settings.isFile;
import static org.neo4j.kernel.configuration.Settings.list;
Expand All @@ -51,7 +54,6 @@
import static org.neo4j.kernel.configuration.Settings.min;
import static org.neo4j.kernel.configuration.Settings.range;
import static org.neo4j.kernel.configuration.Settings.setting;
import static org.neo4j.helpers.collection.MapUtil.stringMap;

public class SettingsTest
{
Expand Down Expand Up @@ -86,6 +88,25 @@ public void testList()

Setting<List<Integer>> setting3 = setting( "foo", list( ",", INTEGER ), "" );
assertThat( setting3.apply( map( stringMap() ) ).toString(), equalTo( "[]" ) );

Setting<List<Integer>> setting4 = setting( "foo", list( ",", INTEGER ), "1, 2,3, 4, 5 " );
assertThat( setting4.apply( map( stringMap() ) ).toString(), equalTo( "[1, 2, 3, 4, 5]" ) );

Setting<List<Integer>> setting5 = setting( "foo", list( ",", INTEGER ), "1, 2,3, 4, " );
assertThat( setting5.apply( map( stringMap() ) ).toString(), equalTo( "[1, 2, 3, 4]" ) );
}

@Test
public void testStringList()
{
Setting<List<String>> setting1 = setting( "apa", STRING_LIST, "foo,bar,baz" );
assertEquals( Arrays.asList( "foo", "bar", "baz" ), setting1.apply( map( stringMap() ) ) );

Setting<List<String>> setting2 = setting( "apa", STRING_LIST, "foo, bar, BAZ " );
assertEquals( Arrays.asList( "foo", "bar", "BAZ" ), setting2.apply( map( stringMap() ) ) );

Setting<List<String>> setting3 = setting( "apa", STRING_LIST, "" );
assertEquals( Collections.emptyList(), setting3.apply( map( stringMap() ) ) );
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,22 @@

import org.neo4j.graphdb.config.Setting;
import org.neo4j.graphdb.factory.Description;
import org.neo4j.kernel.configuration.Settings;
import org.neo4j.kernel.IdType;

import static org.neo4j.kernel.IdType.NODE;
import static org.neo4j.kernel.IdType.RELATIONSHIP;
import static org.neo4j.kernel.configuration.Settings.EMPTY;
import static org.neo4j.kernel.configuration.Settings.list;
import static org.neo4j.kernel.configuration.Settings.optionsIgnoreCase;
import static org.neo4j.kernel.configuration.Settings.setting;

/**
* Enterprise edition specific settings
*/
public class EnterpriseEditionSettings
{
@Description( "Specified names of id types (comma separated) that should be reused. " +
"Currently only 'RELATIONSHIP' type is supported. " )
public static Setting<List<String>> idTypesToReuse =
Settings.setting( "dbms.ids.reuse.types.override", Settings.STRING_LIST, "" );

"Currently only 'node' and 'relationship' types are supported. " )
public static Setting<List<IdType>> idTypesToReuse = setting(
"dbms.ids.reuse.types.override", list( ",", optionsIgnoreCase( NODE, RELATIONSHIP ) ), EMPTY );
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
*/
package org.neo4j.kernel.impl.enterprise.id;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
Expand All @@ -35,6 +34,7 @@
* Allow to reuse predefined id types that are reused in community and in
* addition to that allow additional id types to reuse be specified by
* {@link EnterpriseEditionSettings#idTypesToReuse} setting.
*
* @see IdType
* @see IdTypeConfiguration
*/
Expand All @@ -43,7 +43,7 @@ public class EnterpriseIdTypeConfigurationProvider extends CommunityIdTypeConfig

private final Set<IdType> typesToReuse;

public EnterpriseIdTypeConfigurationProvider(Config config)
public EnterpriseIdTypeConfigurationProvider( Config config )
{
typesToReuse = configureReusableTypes( config );
}
Expand All @@ -56,15 +56,9 @@ protected Set<IdType> getTypesToReuse()

private EnumSet<IdType> configureReusableTypes( Config config )
{
List<String> typeNames = config.get( EnterpriseEditionSettings.idTypesToReuse );
List<IdType> idTypes = new ArrayList<>();
for ( String idType : typeNames )
{
idTypes.add( IdType.valueOf( idType ) );
}

EnumSet<IdType> types = EnumSet.copyOf( super.getTypesToReuse() );
types.addAll( idTypes );
List<IdType> configuredTypes = config.get( EnterpriseEditionSettings.idTypesToReuse );
types.addAll( configuredTypes );
return types;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Copyright (c) 2002-2016 "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 Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.kernel.impl.enterprise.configuration;

import org.apache.commons.lang3.StringUtils;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.neo4j.graphdb.config.InvalidSettingException;
import org.neo4j.kernel.IdType;
import org.neo4j.kernel.configuration.Config;

import static org.hamcrest.Matchers.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.neo4j.helpers.collection.MapUtil.stringMap;
import static org.neo4j.kernel.impl.enterprise.configuration.EnterpriseEditionSettings.idTypesToReuse;

public class EnterpriseEditionSettingsTest
{
@Test
public void idTypesToReuseAllowedValues()
{
for ( IdType type : IdType.values() )
{
if ( type == IdType.NODE || type == IdType.RELATIONSHIP )
{
assertIdTypesToReuseAllows( type );
}
else
{
assertIdTypesToReuseDisallows( type );
}
}

assertIdTypesToReuseAllows( IdType.NODE, IdType.RELATIONSHIP );
assertIdTypesToReuseAllows( IdType.RELATIONSHIP, IdType.NODE );

assertIdTypesToReuseDisallows( IdType.NODE, IdType.RELATIONSHIP, IdType.RELATIONSHIP_GROUP );
assertIdTypesToReuseDisallows( IdType.SCHEMA, IdType.NEOSTORE_BLOCK );
}

@Test
public void idTypesToReuseCaseInsensitive()
{
Config config1 = new Config( stringMap( idTypesToReuse.name(), "node, relationship" ) );
assertEquals( asList( IdType.NODE, IdType.RELATIONSHIP ), config1.get( idTypesToReuse ) );

Config config2 = new Config( stringMap( idTypesToReuse.name(), "rElAtIoNshiP, NoDe" ) );
assertEquals( asList( IdType.RELATIONSHIP, IdType.NODE ), config2.get( idTypesToReuse ) );
}

private static void assertIdTypesToReuseAllows( IdType type, IdType... otherTypes )
{
Config config = configWithIdTypes( type, otherTypes );
List<IdType> types = config.get( idTypesToReuse );
assertEquals( asList( type, otherTypes ), types );
}

private static void assertIdTypesToReuseDisallows( IdType type, IdType... otherTypes )
{
Config config = configWithIdTypes( type, otherTypes );
try
{
config.get( idTypesToReuse );
fail( "Exception expected" );
}
catch ( Exception e )
{
assertThat( e, instanceOf( InvalidSettingException.class ) );
}
}

private static Config configWithIdTypes( IdType type, IdType... otherTypes )
{
String value = stringList( type, otherTypes );
return new Config( stringMap( idTypesToReuse.name(), value ) );
}

@SafeVarargs
private static <T> String stringList( T element, T... elements )
{
return StringUtils.join( asList( element, elements ), "," );
}

@SafeVarargs
private static <T> List<T> asList( T element, T... elements )
{
List<T> list = new ArrayList<>();
list.add( element );
Collections.addAll( list, elements );
return list;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public static List<Object[]> data()
return Arrays.asList( new Object[]{IdType.PROPERTY},
new Object[]{IdType.STRING_BLOCK},
new Object[]{IdType.ARRAY_BLOCK},
new Object[]{IdType.NODE},
new Object[]{IdType.RELATIONSHIP},
new Object[]{IdType.NODE_LABELS} );
}
Expand All @@ -63,9 +64,9 @@ public EnterpriseIdTypeConfigurationProviderTest( IdType reusableType )
public void nonReusableTypeConfiguration()
{
IdTypeConfigurationProvider provider = createIdTypeProvider();
IdTypeConfiguration typeConfiguration = provider.getIdTypeConfiguration( IdType.NODE );
assertFalse( "Node ids are not reusable.", typeConfiguration.allowAggressiveReuse() );
assertEquals( "Node ids are not reusable.", 1024, typeConfiguration.getGrabSize() );
IdTypeConfiguration typeConfiguration = provider.getIdTypeConfiguration( IdType.SCHEMA );
assertFalse( "Schema record ids are not reusable.", typeConfiguration.allowAggressiveReuse() );
assertEquals( "Schema record ids are not reusable.", 1024, typeConfiguration.getGrabSize() );
}

@Test
Expand All @@ -80,9 +81,9 @@ public void reusableTypeConfiguration()
private IdTypeConfigurationProvider createIdTypeProvider()
{
Map<String,String> params = MapUtil.stringMap( EnterpriseEditionSettings.idTypesToReuse.name(),
IdType.RELATIONSHIP.name() );
IdType.NODE + "," + IdType.RELATIONSHIP );
Config config = new Config( params );
return new EnterpriseIdTypeConfigurationProvider( config );
}

}
}

0 comments on commit 37e1daa

Please sign in to comment.