/** * Copyright (c) 2002-2012 "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.consistency.checking; import org.neo4j.consistency.report.ConsistencyReport; import org.neo4j.consistency.store.DiffRecordAccess; import org.neo4j.consistency.store.RecordAccess; import org.neo4j.consistency.store.RecordAccessStub; import org.neo4j.consistency.store.RecordReference; import org.neo4j.kernel.impl.nioneo.store.AbstractBaseRecord; import org.neo4j.kernel.impl.nioneo.store.DynamicRecord; import org.neo4j.kernel.impl.nioneo.store.NeoStoreRecord; import org.neo4j.kernel.impl.nioneo.store.NodeRecord; import org.neo4j.kernel.impl.nioneo.store.PropertyBlock; import org.neo4j.kernel.impl.nioneo.store.PropertyIndexRecord; import org.neo4j.kernel.impl.nioneo.store.PropertyRecord; import org.neo4j.kernel.impl.nioneo.store.PropertyType; import org.neo4j.kernel.impl.nioneo.store.RecordStore; import org.neo4j.kernel.impl.nioneo.store.RelationshipRecord; import org.neo4j.kernel.impl.nioneo.store.RelationshipTypeRecord; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; public abstract class RecordCheckTestBase<RECORD extends AbstractBaseRecord, REPORT extends ConsistencyReport<RECORD, REPORT>, CHECKER extends RecordCheck<RECORD, REPORT>> { public static final int NONE = -1; private final CHECKER checker; private final Class<REPORT> reportClass; private final RecordAccessStub records = new RecordAccessStub(); RecordCheckTestBase( CHECKER checker, Class<REPORT> reportClass ) { this.checker = checker; this.reportClass = reportClass; } public static PrimitiveRecordCheck<NodeRecord, ConsistencyReport.NodeConsistencyReport> dummyNodeCheck() { return new NodeRecordCheck() { @Override public void check( NodeRecord record, ConsistencyReport.NodeConsistencyReport report, RecordAccess records ) { } @Override public void checkChange( NodeRecord oldRecord, NodeRecord newRecord, ConsistencyReport.NodeConsistencyReport report, DiffRecordAccess records ) { } }; } public static PrimitiveRecordCheck<RelationshipRecord, ConsistencyReport.RelationshipConsistencyReport> dummyRelationshipChecker() { return new RelationshipRecordCheck() { @Override public void check( RelationshipRecord record, ConsistencyReport.RelationshipConsistencyReport report, RecordAccess records ) { } @Override public void checkChange( RelationshipRecord oldRecord, RelationshipRecord newRecord, ConsistencyReport.RelationshipConsistencyReport report, DiffRecordAccess records ) { } }; } public static RecordCheck<PropertyRecord, ConsistencyReport.PropertyConsistencyReport> dummyPropertyChecker() { return new RecordCheck<PropertyRecord, ConsistencyReport.PropertyConsistencyReport>() { @Override public void check( PropertyRecord record, ConsistencyReport.PropertyConsistencyReport report, RecordAccess records ) { } @Override public void checkChange( PropertyRecord oldRecord, PropertyRecord newRecord, ConsistencyReport.PropertyConsistencyReport report, DiffRecordAccess records ) { } }; } public static PrimitiveRecordCheck<NeoStoreRecord, ConsistencyReport.NeoStoreConsistencyReport> dummyNeoStoreCheck() { return new NeoStoreCheck() { @Override public void check( NeoStoreRecord record, ConsistencyReport.NeoStoreConsistencyReport report, RecordAccess records ) { } @Override public void checkChange( NeoStoreRecord oldRecord, NeoStoreRecord newRecord, ConsistencyReport.NeoStoreConsistencyReport report, DiffRecordAccess records ) { } }; } public static RecordCheck<DynamicRecord, ConsistencyReport.DynamicConsistencyReport> dummyDynamicCheck( RecordStore<DynamicRecord> store, DynamicStore dereference ) { return new DynamicRecordCheck(store, dereference ) { @Override public void check( DynamicRecord record, ConsistencyReport.DynamicConsistencyReport report, RecordAccess records ) { } @Override public void checkChange( DynamicRecord oldRecord, DynamicRecord newRecord, ConsistencyReport.DynamicConsistencyReport report, DiffRecordAccess records ) { } }; } public static RecordCheck<PropertyIndexRecord, ConsistencyReport.PropertyKeyConsistencyReport> dummyPropertyKeyCheck() { return new PropertyKeyRecordCheck() { @Override public void check( PropertyIndexRecord record, ConsistencyReport.PropertyKeyConsistencyReport report, RecordAccess records ) { } @Override public void checkChange( PropertyIndexRecord oldRecord, PropertyIndexRecord newRecord, ConsistencyReport.PropertyKeyConsistencyReport report, DiffRecordAccess records ) { } }; } public static RecordCheck<RelationshipTypeRecord, ConsistencyReport.LabelConsistencyReport> dummyRelationshipLabelCheck() { return new RelationshipLabelRecordCheck() { @Override public void check( RelationshipTypeRecord record, ConsistencyReport.LabelConsistencyReport report, RecordAccess records ) { } @Override public void checkChange( RelationshipTypeRecord oldRecord, RelationshipTypeRecord newRecord, ConsistencyReport.LabelConsistencyReport report, DiffRecordAccess records ) { } }; } final REPORT check( RECORD record ) { return check( reportClass, checker, record, records ); } final REPORT checkChange( RECORD oldRecord, RECORD newRecord ) { return checkChange( reportClass, checker, oldRecord, newRecord, records ); } public static <RECORD extends AbstractBaseRecord, REPORT extends ConsistencyReport<RECORD, REPORT>> REPORT check( Class<REPORT> reportClass, RecordCheck<RECORD, REPORT> checker, RECORD record, final RecordAccessStub records ) { REPORT report = records.mockReport( reportClass, record ); checker.check( record, report, records ); records.checkDeferred(); return report; } static <RECORD extends AbstractBaseRecord, REPORT extends ConsistencyReport<RECORD, REPORT>> REPORT checkChange( Class<REPORT> reportClass, RecordCheck<RECORD, REPORT> checker, RECORD oldRecord, RECORD newRecord, final RecordAccessStub records ) { REPORT report = records.mockReport( reportClass, oldRecord, newRecord ); checker.checkChange( oldRecord, newRecord, report, records ); records.checkDeferred(); return report; } <R extends AbstractBaseRecord> R addChange( R oldRecord, R newRecord ) { return records.addChange( oldRecord, newRecord ); } <R extends AbstractBaseRecord> R add( R record ) { return records.add( record ); } DynamicRecord addKeyName( DynamicRecord name ) { return records.addKeyName( name ); } DynamicRecord addLabelName( DynamicRecord name ) { return records.addLabelName( name ); } public static DynamicRecord string( DynamicRecord record ) { record.setType( PropertyType.STRING.intValue() ); return record; } public static DynamicRecord array( DynamicRecord record ) { record.setType( PropertyType.ARRAY.intValue() ); return record; } static PropertyBlock propertyBlock( PropertyIndexRecord key, DynamicRecord value ) { PropertyType type; if ( value.getType() == PropertyType.STRING.intValue() ) { type = PropertyType.STRING; } else if ( value.getType() == PropertyType.ARRAY.intValue() ) { type = PropertyType.ARRAY; } else { fail( "Dynamic record must be either STRING or ARRAY" ); return null; } return propertyBlock( key, type, value.getId() ); } public static PropertyBlock propertyBlock( PropertyIndexRecord key, PropertyType type, long value ) { PropertyBlock block = new PropertyBlock(); block.setSingleBlock( key.getId() | (((long) type.intValue()) << 24) | (value << 28) ); return block; } public static <R extends AbstractBaseRecord> R inUse( R record ) { record.setInUse( true ); return record; } public static <R extends AbstractBaseRecord> R notInUse( R record ) { record.setInUse( false ); return record; } @SuppressWarnings("unchecked") public static void verifyOnlyReferenceDispatch( ConsistencyReport report ) { verify( report, atLeast( 0 ) ) .forReference( any( RecordReference.class ), any( ComparativeRecordChecker.class ) ); verifyNoMoreInteractions( report ); } }