diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 034c6be1d..38beecc75 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,9 +27,10 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up JDK 1.8 - uses: actions/setup-java@v1 + uses: actions/setup-java@v2.1.0 with: - java-version: 1.8.0.212 + distribution: 'zulu' + java-version: '8' java-package: jdk architecture: x64 diff --git a/README.md b/README.md index 4b8fd793e..7b2ad1c85 100644 --- a/README.md +++ b/README.md @@ -248,13 +248,13 @@ try (Session session = db.createSession()) { Migration migration1 = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { @Override - public void migrate(Instruction instruction) { - instruction.forDatabase() + public void migrate(Instruction instructions) { + instructions.forDatabase() // make a non-secure db to secure db .addPassword("test-user", "test-password"); - // create instruction for existing repository - instruction.forRepository(OldClass.class, null) + // create instructions for existing repository + instructions.forRepository(OldClass.class, null) // rename the repository (in case of entity name changes) .renameRepository("migrated", null) @@ -288,8 +288,8 @@ Migration migration1 = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { Migration migration2 = new Migration(2, 3) { @Override - public void migrate(Instruction instruction) { - instruction.forCollection("test") + public void migrate(Instruction instructions) { + instructions.forCollection("test") .addField("fullName", "Dummy Name"); } }; diff --git a/TODO.md b/TODO.md index e88537ed5..b0fe2bdb8 100644 --- a/TODO.md +++ b/TODO.md @@ -153,4 +153,11 @@ https://docs.yugabyte.com/latest/architecture/docdb/persistence/ https://blog.yugabyte.com/enhancing-rocksdb-for-speed-scale/ +## Query Optimization + - https://www.javatpoint.com/dbms-transforming-relational-expressions + - http://www.cbcb.umd.edu/confcour/Spring2014/CMSC424/query_optimization.pdf + - https://www.tutorialcup.com/dbms/query-optimization.htm + - https://www.geeksforgeeks.org/query-optimization-in-relational-algebra/ + + diff --git a/nitrite-android-example/build.gradle b/nitrite-android-example/build.gradle index c8a920712..358d3d865 100644 --- a/nitrite-android-example/build.gradle +++ b/nitrite-android-example/build.gradle @@ -21,7 +21,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.0.2' + classpath 'com.android.tools.build:gradle:4.1.1' } } @@ -48,16 +48,16 @@ android { compileSdkVersion 28 - defaultConfig { applicationId "org.dizitart.no2.example.android" minSdkVersion 19 - targetSdkVersion 29 + targetSdkVersion 28 versionCode 1 versionName "1.0" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" +// multiDexEnabled true + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { @@ -72,6 +72,7 @@ android { } compileOptions { +// coreLibraryDesugaringEnabled true sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } @@ -88,12 +89,13 @@ dependencies { implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support:multidex:1.0.3' - implementation 'com.android.support.constraint:constraint-layout:2.0.2' + implementation 'com.android.support.constraint:constraint-layout:2.0.4' implementation 'com.android.support:design:28.0.0' annotationProcessor "org.projectlombok:lombok:1.18.14" testImplementation 'junit:junit:4.13.1' - testAnnotationProcessor "org.projectlombok:lombok:1.18.12" + testImplementation 'org.mockito:mockito-core:3.9.0' + testAnnotationProcessor "org.projectlombok:lombok:1.18.14" androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' } diff --git a/nitrite-android-example/src/main/java/org/dizitart/no2/example/android/User.java b/nitrite-android-example/src/main/java/org/dizitart/no2/example/android/User.java index 44e34fbba..628ef3acf 100644 --- a/nitrite-android-example/src/main/java/org/dizitart/no2/example/android/User.java +++ b/nitrite-android-example/src/main/java/org/dizitart/no2/example/android/User.java @@ -17,8 +17,8 @@ package org.dizitart.no2.example.android; import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; /** * @author Anindya Chatterjee. diff --git a/nitrite-bom/build.gradle b/nitrite-bom/build.gradle index 5d434edb6..d3a848cf9 100644 --- a/nitrite-bom/build.gradle +++ b/nitrite-bom/build.gradle @@ -22,7 +22,6 @@ dependencies { api project(":nitrite-mvstore-adapter") api project(":nitrite-rocksdb-adapter") - api project(":nitrite-mapdb-adapter") api "org.slf4j:slf4j-api:1.7.30" api "org.objenesis:objenesis:2.6" @@ -34,7 +33,7 @@ dependencies { api "org.mapdb:mapdb:3.0.8" api "com.h2database:h2-mvstore:1.4.200" api "com.squareup.okhttp3:okhttp:4.9.0" - api "org.rocksdb:rocksdbjni:6.11.6" + api "org.rocksdb:rocksdbjni:6.20.3" api "com.esotericsoftware:kryo:4.0.2" api "org.locationtech.jts:jts-core:1.17.1" api "commons-codec:commons-codec:1.15" diff --git a/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/JacksonExtension.java b/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/common/mapper/JacksonExtension.java similarity index 90% rename from nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/JacksonExtension.java rename to nitrite-jackson-mapper/src/main/java/org/dizitart/no2/common/mapper/JacksonExtension.java index 2020b2048..d6be1d6e1 100644 --- a/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/JacksonExtension.java +++ b/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/common/mapper/JacksonExtension.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.dizitart.no2.mapper; +package org.dizitart.no2.common.mapper; import com.fasterxml.jackson.databind.Module; @@ -24,6 +24,6 @@ * @author Anindya Chatterjee */ public interface JacksonExtension { - List> getDataTypes(); + List> getSupportedTypes(); Module getModule(); } diff --git a/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/JacksonMapper.java b/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/common/mapper/JacksonMapper.java similarity index 97% rename from nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/JacksonMapper.java rename to nitrite-jackson-mapper/src/main/java/org/dizitart/no2/common/mapper/JacksonMapper.java index e9789712d..0af159b4f 100644 --- a/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/JacksonMapper.java +++ b/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/common/mapper/JacksonMapper.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.dizitart.no2.mapper; +package org.dizitart.no2.common.mapper; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.core.JsonParser; @@ -29,7 +29,7 @@ import org.dizitart.no2.collection.Document; import org.dizitart.no2.common.util.ObjectUtils; import org.dizitart.no2.exceptions.ObjectMappingException; -import org.dizitart.no2.mapper.extensions.NitriteIdExtension; +import org.dizitart.no2.common.mapper.extensions.NitriteIdExtension; import java.io.IOException; import java.lang.reflect.Modifier; @@ -164,7 +164,7 @@ protected Document convertToDocument(Source source) { } private void loadJacksonExtension(JacksonExtension jacksonExtension, ObjectMapper objectMapper) { - for (Class dataType : jacksonExtension.getDataTypes()) { + for (Class dataType : jacksonExtension.getSupportedTypes()) { addValueType(dataType); } objectMapper.registerModule(jacksonExtension.getModule()); diff --git a/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/JacksonMapperModule.java b/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/common/mapper/JacksonMapperModule.java similarity index 84% rename from nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/JacksonMapperModule.java rename to nitrite-jackson-mapper/src/main/java/org/dizitart/no2/common/mapper/JacksonMapperModule.java index 5ac1f1b6e..9fe5f54bd 100644 --- a/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/JacksonMapperModule.java +++ b/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/common/mapper/JacksonMapperModule.java @@ -14,13 +14,15 @@ * limitations under the License. */ -package org.dizitart.no2.mapper; +package org.dizitart.no2.common.mapper; -import org.dizitart.no2.module.NitriteModule; -import org.dizitart.no2.module.NitritePlugin; +import org.dizitart.no2.common.module.NitriteModule; +import org.dizitart.no2.common.module.NitritePlugin; import java.util.Set; +import static org.dizitart.no2.common.util.Iterables.setOf; + /** * @author Anindya Chatterjee */ diff --git a/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/extensions/NitriteIdDeserializer.java b/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/common/mapper/extensions/NitriteIdDeserializer.java similarity index 96% rename from nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/extensions/NitriteIdDeserializer.java rename to nitrite-jackson-mapper/src/main/java/org/dizitart/no2/common/mapper/extensions/NitriteIdDeserializer.java index 5d45b5370..f69a97aac 100644 --- a/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/extensions/NitriteIdDeserializer.java +++ b/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/common/mapper/extensions/NitriteIdDeserializer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.dizitart.no2.mapper.extensions; +package org.dizitart.no2.common.mapper.extensions; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; diff --git a/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/extensions/NitriteIdExtension.java b/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/common/mapper/extensions/NitriteIdExtension.java similarity index 90% rename from nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/extensions/NitriteIdExtension.java rename to nitrite-jackson-mapper/src/main/java/org/dizitart/no2/common/mapper/extensions/NitriteIdExtension.java index 6cb872e84..6523a9991 100644 --- a/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/extensions/NitriteIdExtension.java +++ b/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/common/mapper/extensions/NitriteIdExtension.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package org.dizitart.no2.mapper.extensions; +package org.dizitart.no2.common.mapper.extensions; import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.module.SimpleModule; import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.mapper.JacksonExtension; +import org.dizitart.no2.common.mapper.JacksonExtension; import java.util.List; @@ -34,7 +34,7 @@ public class NitriteIdExtension implements JacksonExtension { @Override - public List> getDataTypes() { + public List> getSupportedTypes() { return listOf(NitriteId.class); } diff --git a/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/extensions/NitriteIdSerializer.java b/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/common/mapper/extensions/NitriteIdSerializer.java similarity index 96% rename from nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/extensions/NitriteIdSerializer.java rename to nitrite-jackson-mapper/src/main/java/org/dizitart/no2/common/mapper/extensions/NitriteIdSerializer.java index b39611599..2262db37d 100644 --- a/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/mapper/extensions/NitriteIdSerializer.java +++ b/nitrite-jackson-mapper/src/main/java/org/dizitart/no2/common/mapper/extensions/NitriteIdSerializer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.dizitart.no2.mapper.extensions; +package org.dizitart.no2.common.mapper.extensions; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/common/mapper/JacksonMapperModuleTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/common/mapper/JacksonMapperModuleTest.java new file mode 100644 index 000000000..d06ce7466 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/common/mapper/JacksonMapperModuleTest.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.mapper; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class JacksonMapperModuleTest { + + @Test + public void testPlugins() { + assertEquals(1, (new JacksonMapperModule()).plugins().size()); + } +} + diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/common/mapper/JacksonMapperTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/common/mapper/JacksonMapperTest.java new file mode 100644 index 000000000..72eec9f15 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/common/mapper/JacksonMapperTest.java @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.mapper; + +import com.fasterxml.jackson.databind.DeserializationConfig; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.cfg.ContextAttributes; +import com.fasterxml.jackson.databind.introspect.VisibilityChecker; +import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator; +import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.BinaryNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.extensions.NitriteIdExtension; +import org.dizitart.no2.exceptions.ObjectMappingException; +import org.junit.Test; + +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; +import java.text.DateFormat; + +import static org.junit.Assert.*; + +public class JacksonMapperTest { + @Test + public void testConstructor() { + ObjectMapper objectMapper = (new JacksonMapper()).getObjectMapper(); + PolymorphicTypeValidator polymorphicTypeValidator = objectMapper.getPolymorphicTypeValidator(); + assertTrue(polymorphicTypeValidator instanceof LaissezFaireSubTypeValidator); + VisibilityChecker visibilityChecker = objectMapper.getVisibilityChecker(); + assertTrue(visibilityChecker instanceof VisibilityChecker.Std); + assertNull(objectMapper.getPropertyNamingStrategy()); + assertTrue(objectMapper + .getDeserializationContext() instanceof com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.Impl); + assertSame(objectMapper.getFactory(), objectMapper.getJsonFactory()); + assertTrue(objectMapper.getSerializerFactory() instanceof com.fasterxml.jackson.databind.ser.BeanSerializerFactory); + assertTrue(objectMapper + .getSerializerProvider() instanceof com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.Impl); + assertTrue(objectMapper + .getSerializerProviderInstance() instanceof com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.Impl); + assertTrue( + objectMapper.getSubtypeResolver() instanceof com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver); + DeserializationConfig deserializationConfig = objectMapper.getDeserializationConfig(); + assertTrue(deserializationConfig + .getAnnotationIntrospector() instanceof com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector); + assertNull(deserializationConfig.getActiveView()); + assertNull(deserializationConfig.getHandlerInstantiator()); + assertSame(visibilityChecker, deserializationConfig.getDefaultVisibilityChecker()); + assertTrue(deserializationConfig + .getClassIntrospector() instanceof com.fasterxml.jackson.databind.introspect.BasicClassIntrospector); + DateFormat expectedDateFormat = objectMapper.getDateFormat(); + assertSame(expectedDateFormat, deserializationConfig.getDateFormat()); + assertNull(deserializationConfig.getFullRootName()); + JsonNodeFactory expectedNodeFactory = objectMapper.getNodeFactory(); + assertSame(expectedNodeFactory, deserializationConfig.getNodeFactory()); + assertSame(polymorphicTypeValidator, deserializationConfig.getPolymorphicTypeValidator()); + assertNull(deserializationConfig.getDefaultMergeable()); + assertEquals(237020288, deserializationConfig.getDeserializationFeatures()); + assertTrue(deserializationConfig.getAttributes() instanceof ContextAttributes.Impl); + } + + @Test + public void testConstructor2() { + NitriteIdExtension nitriteIdExtension = new NitriteIdExtension(); + NitriteIdExtension nitriteIdExtension1 = new NitriteIdExtension(); + ObjectMapper objectMapper = (new JacksonMapper(nitriteIdExtension, nitriteIdExtension1, new NitriteIdExtension())) + .getObjectMapper(); + PolymorphicTypeValidator polymorphicTypeValidator = objectMapper.getPolymorphicTypeValidator(); + assertTrue(polymorphicTypeValidator instanceof LaissezFaireSubTypeValidator); + VisibilityChecker visibilityChecker = objectMapper.getVisibilityChecker(); + assertTrue(visibilityChecker instanceof VisibilityChecker.Std); + assertNull(objectMapper.getPropertyNamingStrategy()); + assertTrue(objectMapper + .getDeserializationContext() instanceof com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.Impl); + assertSame(objectMapper.getFactory(), objectMapper.getJsonFactory()); + assertTrue(objectMapper.getSerializerFactory() instanceof com.fasterxml.jackson.databind.ser.BeanSerializerFactory); + assertTrue(objectMapper + .getSerializerProvider() instanceof com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.Impl); + assertTrue(objectMapper + .getSerializerProviderInstance() instanceof com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.Impl); + assertTrue( + objectMapper.getSubtypeResolver() instanceof com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver); + DeserializationConfig deserializationConfig = objectMapper.getDeserializationConfig(); + assertTrue(deserializationConfig + .getAnnotationIntrospector() instanceof com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector); + assertNull(deserializationConfig.getActiveView()); + assertNull(deserializationConfig.getHandlerInstantiator()); + assertSame(visibilityChecker, deserializationConfig.getDefaultVisibilityChecker()); + assertTrue(deserializationConfig + .getClassIntrospector() instanceof com.fasterxml.jackson.databind.introspect.BasicClassIntrospector); + DateFormat expectedDateFormat = objectMapper.getDateFormat(); + assertSame(expectedDateFormat, deserializationConfig.getDateFormat()); + assertNull(deserializationConfig.getFullRootName()); + JsonNodeFactory expectedNodeFactory = objectMapper.getNodeFactory(); + assertSame(expectedNodeFactory, deserializationConfig.getNodeFactory()); + assertSame(polymorphicTypeValidator, deserializationConfig.getPolymorphicTypeValidator()); + assertNull(deserializationConfig.getDefaultMergeable()); + assertEquals(237020288, deserializationConfig.getDeserializationFeatures()); + assertTrue(deserializationConfig.getAttributes() instanceof ContextAttributes.Impl); + } + + @Test + public void testConstructor3() { + ObjectMapper objectMapper = (new JacksonMapper(new NitriteIdExtension())).getObjectMapper(); + PolymorphicTypeValidator polymorphicTypeValidator = objectMapper.getPolymorphicTypeValidator(); + assertTrue(polymorphicTypeValidator instanceof LaissezFaireSubTypeValidator); + VisibilityChecker visibilityChecker = objectMapper.getVisibilityChecker(); + assertTrue(visibilityChecker instanceof VisibilityChecker.Std); + assertNull(objectMapper.getPropertyNamingStrategy()); + assertTrue(objectMapper + .getDeserializationContext() instanceof com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.Impl); + assertSame(objectMapper.getFactory(), objectMapper.getJsonFactory()); + assertTrue(objectMapper.getSerializerFactory() instanceof com.fasterxml.jackson.databind.ser.BeanSerializerFactory); + assertTrue(objectMapper + .getSerializerProvider() instanceof com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.Impl); + assertTrue(objectMapper + .getSerializerProviderInstance() instanceof com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.Impl); + assertTrue( + objectMapper.getSubtypeResolver() instanceof com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver); + DeserializationConfig deserializationConfig = objectMapper.getDeserializationConfig(); + assertTrue(deserializationConfig + .getAnnotationIntrospector() instanceof com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector); + assertNull(deserializationConfig.getActiveView()); + assertNull(deserializationConfig.getHandlerInstantiator()); + assertSame(visibilityChecker, deserializationConfig.getDefaultVisibilityChecker()); + assertTrue(deserializationConfig + .getClassIntrospector() instanceof com.fasterxml.jackson.databind.introspect.BasicClassIntrospector); + DateFormat expectedDateFormat = objectMapper.getDateFormat(); + assertSame(expectedDateFormat, deserializationConfig.getDateFormat()); + assertNull(deserializationConfig.getFullRootName()); + JsonNodeFactory expectedNodeFactory = objectMapper.getNodeFactory(); + assertSame(expectedNodeFactory, deserializationConfig.getNodeFactory()); + assertSame(polymorphicTypeValidator, deserializationConfig.getPolymorphicTypeValidator()); + assertNull(deserializationConfig.getDefaultMergeable()); + assertEquals(237020288, deserializationConfig.getDeserializationFeatures()); + assertTrue(deserializationConfig.getAttributes() instanceof ContextAttributes.Impl); + } + + @Test + public void testCreateObjectMapper() { + ObjectMapper actualCreateObjectMapperResult = (new JacksonMapper()).createObjectMapper(); + PolymorphicTypeValidator polymorphicTypeValidator = actualCreateObjectMapperResult.getPolymorphicTypeValidator(); + assertTrue(polymorphicTypeValidator instanceof LaissezFaireSubTypeValidator); + VisibilityChecker visibilityChecker = actualCreateObjectMapperResult.getVisibilityChecker(); + assertTrue(visibilityChecker instanceof VisibilityChecker.Std); + assertNull(actualCreateObjectMapperResult.getPropertyNamingStrategy()); + assertTrue(actualCreateObjectMapperResult + .getDeserializationContext() instanceof com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.Impl); + assertSame(actualCreateObjectMapperResult.getFactory(), actualCreateObjectMapperResult.getJsonFactory()); + assertTrue(actualCreateObjectMapperResult + .getSerializerFactory() instanceof com.fasterxml.jackson.databind.ser.BeanSerializerFactory); + assertTrue(actualCreateObjectMapperResult + .getSerializerProvider() instanceof com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.Impl); + assertTrue(actualCreateObjectMapperResult + .getSerializerProviderInstance() instanceof com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.Impl); + assertTrue(actualCreateObjectMapperResult + .getSubtypeResolver() instanceof com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver); + DeserializationConfig deserializationConfig = actualCreateObjectMapperResult.getDeserializationConfig(); + assertTrue(deserializationConfig.getAttributes() instanceof ContextAttributes.Impl); + assertTrue(deserializationConfig + .getAnnotationIntrospector() instanceof com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector); + assertNull(deserializationConfig.getActiveView()); + assertEquals(237020288, deserializationConfig.getDeserializationFeatures()); + DateFormat expectedDateFormat = actualCreateObjectMapperResult.getDateFormat(); + assertSame(expectedDateFormat, deserializationConfig.getDateFormat()); + assertNull(deserializationConfig.getDefaultMergeable()); + assertSame(visibilityChecker, deserializationConfig.getDefaultVisibilityChecker()); + assertNull(deserializationConfig.getHandlerInstantiator()); + JsonNodeFactory expectedNodeFactory = actualCreateObjectMapperResult.getNodeFactory(); + assertSame(expectedNodeFactory, deserializationConfig.getNodeFactory()); + assertSame(polymorphicTypeValidator, deserializationConfig.getPolymorphicTypeValidator()); + assertTrue(deserializationConfig + .getClassIntrospector() instanceof com.fasterxml.jackson.databind.introspect.BasicClassIntrospector); + assertNull(deserializationConfig.getFullRootName()); + assertNull(deserializationConfig.getProblemHandlers()); + } + + @Test + public void testConvert() { + JacksonMapper jacksonMapper = new JacksonMapper(); + assertEquals("Source", jacksonMapper.convert("Source", Object.class)); + assertTrue(jacksonMapper.getObjectMapper() + .getSerializerProviderInstance() instanceof com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.Impl); + } + + @Test + public void testConvert2() { + JacksonMapper jacksonMapper = new JacksonMapper(); + jacksonMapper.addValueType(Object.class); + assertEquals("Source", jacksonMapper.convert("Source", Object.class)); + assertTrue(jacksonMapper.getObjectMapper() + .getSerializerProviderInstance() instanceof com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.Impl); + } + + @Test + public void testConvert3() { + JacksonMapper jacksonMapper = new JacksonMapper(); + assertNull(jacksonMapper.convert(null, Object.class)); + } + + @Test + public void testConvert4() { + JacksonMapper jacksonMapper = new JacksonMapper(); + assertEquals(0, ((Integer) jacksonMapper.convert(0, Object.class)).intValue()); + assertTrue(jacksonMapper.getObjectMapper() + .getSerializerProviderInstance() instanceof com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.Impl); + } + + @Test + public void testConvert5() { + JacksonMapper jacksonMapper = new JacksonMapper(); + ArrayNode source = new ArrayNode(new JsonNodeFactory(true)); + assertThrows(ObjectMappingException.class, () -> jacksonMapper.convert(source, Object.class)); + } + + @Test + public void testConvert6() throws UnsupportedEncodingException { + JacksonMapper jacksonMapper = new JacksonMapper(); + BinaryNode source = new BinaryNode("AAAAAAAAAAAAAAAAAAAAAAAA".getBytes(StandardCharsets.UTF_8)); + assertNull(jacksonMapper.convert(source, Object.class)); + } + + @Test + public void testIsValueType() { + JacksonMapper jacksonMapper = new JacksonMapper(); + assertThrows(ObjectMappingException.class, () -> jacksonMapper.isValueType(Object.class)); + } + + @Test + public void testIsValueType2() { + JacksonMapper jacksonMapper = new JacksonMapper(); + jacksonMapper.addValueType(Object.class); + assertTrue(jacksonMapper.isValueType(Object.class)); + } + + @Test + public void testIsValueType3() { + JacksonMapper jacksonMapper = new JacksonMapper(); + assertFalse(jacksonMapper.isValueType(JsonMappingException.class)); + assertTrue(jacksonMapper.getObjectMapper() + .getSerializerProviderInstance() instanceof com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.Impl); + } + + @Test + public void testIsValueType4() { + JacksonMapper jacksonMapper = new JacksonMapper(); + assertFalse(jacksonMapper.isValueType(JsonNode.class)); + } + + @Test + public void testIsValueType5() { + JacksonMapper jacksonMapper = new JacksonMapper(); + assertFalse(jacksonMapper.isValueType(Document.class)); + } + + @Test + public void testIsValue() { + JacksonMapper jacksonMapper = new JacksonMapper(); + assertTrue(jacksonMapper.isValue("Object")); + assertTrue(jacksonMapper.getObjectMapper() + .getSerializerProviderInstance() instanceof com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.Impl); + } + + @Test + public void testIsValue2() { + JacksonMapper jacksonMapper = new JacksonMapper(); + assertFalse(jacksonMapper.isValue(new ArrayNode(new JsonNodeFactory(true)))); + } + + @Test + public void testInitialize() { + JacksonMapper jacksonMapper = new JacksonMapper(); + NitriteConfig nitriteConfig = new NitriteConfig(); + jacksonMapper.initialize(nitriteConfig); + assertEquals(1, nitriteConfig.getSchemaVersion().intValue()); + } + + @Test + public void testConvertFromDocument() { + JacksonMapper jacksonMapper = new JacksonMapper(); + assertNull(jacksonMapper.convertFromDocument(null, Object.class)); + } + + @Test + public void testConvertToDocument() { + JacksonMapper jacksonMapper = new JacksonMapper(); + jacksonMapper.convertToDocument("Source"); + assertTrue(jacksonMapper.getObjectMapper() + .getSerializerProviderInstance() instanceof com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.Impl); + } +} + diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/common/mapper/extensions/NitriteIdDeserializerTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/common/mapper/extensions/NitriteIdDeserializerTest.java new file mode 100644 index 000000000..9aceea44e --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/common/mapper/extensions/NitriteIdDeserializerTest.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.mapper.extensions; + +import org.dizitart.no2.collection.NitriteId; +import org.junit.Test; + +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +public class NitriteIdDeserializerTest { + @Test + public void testConstructor() { + NitriteIdDeserializer actualNitriteIdDeserializer = new NitriteIdDeserializer(); + assertNull(actualNitriteIdDeserializer.getValueType()); + Class expectedValueClass = NitriteId.class; + assertSame(expectedValueClass, actualNitriteIdDeserializer.getValueClass()); + } +} + diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/common/mapper/extensions/NitriteIdExtensionTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/common/mapper/extensions/NitriteIdExtensionTest.java new file mode 100644 index 000000000..2a02ad524 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/common/mapper/extensions/NitriteIdExtensionTest.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.mapper.extensions; + +import org.junit.Assert; +import org.junit.Test; + +public class NitriteIdExtensionTest { + @Test + public void testGetSupportedTypes() { + Assert.assertEquals(1, (new NitriteIdExtension()).getSupportedTypes().size()); + } +} + diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/common/mapper/extensions/NitriteIdSerializerTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/common/mapper/extensions/NitriteIdSerializerTest.java new file mode 100644 index 000000000..a1b7f61eb --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/common/mapper/extensions/NitriteIdSerializerTest.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.mapper.extensions; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; + +public class NitriteIdSerializerTest { + @Test + public void testConstructor() { + NitriteIdSerializer actualNitriteIdSerializer = new NitriteIdSerializer(); + assertNull(actualNitriteIdSerializer.getDelegatee()); + assertFalse(actualNitriteIdSerializer.isUnwrappingSerializer()); + } +} + diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/migrate/MigrationTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/migrate/MigrationTest.java new file mode 100644 index 000000000..16b83e0df --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/migrate/MigrationTest.java @@ -0,0 +1,589 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.migrate; + +import com.github.javafaker.Faker; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.Constants; +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.common.mapper.JacksonMapperModule; +import org.dizitart.no2.exceptions.MigrationException; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.migration.Instructions; +import org.dizitart.no2.migration.Migration; +import org.dizitart.no2.migration.TypeConverter; +import org.dizitart.no2.mvstore.MVStoreModule; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.integration.repository.Retry; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.UUID; + +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.dizitart.no2.integration.repository.BaseObjectRepositoryTest.getRandomTempDbFile; +import static org.dizitart.no2.integration.repository.TestUtil.createDb; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class MigrationTest { + private final String dbPath = getRandomTempDbFile(); + private Nitrite db; + private Faker faker; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + db = createDb(dbPath, new JacksonMapperModule()); + faker = new Faker(); + } + + @After + public void cleanUp() throws IOException { + if (!db.isClosed()) { + db.close(); + } + + Files.delete(Paths.get(dbPath)); + } + + @Test + public void testRepositoryMigrate() { + ObjectRepository oldRepo = db.getRepository(OldClass.class, "demo1"); + for (int i = 0; i < 10; i++) { + OldClass old = new OldClass(); + old.setEmpId(String.valueOf(faker.number().randomNumber())); + old.setFirstName(faker.name().firstName()); + old.setLastName(faker.name().lastName()); + old.setUuid(UUID.randomUUID().toString()); + + OldClass.Literature literature = new OldClass.Literature(); + literature.setRatings((float) faker.number().randomDouble(2, 1, 5)); + literature.setText(faker.lorem().paragraph()); + old.setLiterature(literature); + + oldRepo.insert(old); + } + + db.close(); + + Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { + @Override + public void migrate(Instructions instruction) { + instruction.forDatabase() + .addPassword("test-user", "test-password"); + + instruction.forRepository(OldClass.class, "demo1") + .renameRepository("new", null) + .changeDataType("empId", (TypeConverter) Long::parseLong) + .changeIdField(Fields.withNames("uuid"), Fields.withNames("empId")) + .deleteField("uuid") + .renameField("lastName", "familyName") + .addField("fullName", document -> document.get("firstName", String.class) + " " + + document.get("familyName", String.class)) + .dropIndex("firstName") + .dropIndex("literature.text") + .changeDataType("literature.ratings", (TypeConverter) Math::round); + } + }; + + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compress(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate("test-user", "test-password"); + + ObjectRepository newRepo = db.getRepository(NewClass.class); + assertEquals(newRepo.size(), 10); + assertTrue(db.listCollectionNames().isEmpty()); + assertTrue(db.listKeyedRepository().isEmpty()); + + assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 2); + } + + @Test + public void testCollectionMigrate() { + NitriteCollection collection = db.getCollection("test"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + document.put("bloodGroup", faker.name().bloodGroup()); + document.put("age", faker.number().randomDigit()); + + collection.insert(document); + } + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "bloodGroup"); + db.close(); + + Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { + @Override + public void migrate(Instructions instruction) { + instruction.forDatabase() + .addPassword("test-user", "test-password"); + + instruction.forCollection("test") + .rename("testCollectionMigrate") + .deleteField("lastName"); + } + }; + + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate("test-user", "test-password"); + + collection = db.getCollection("testCollectionMigrate"); + assertTrue(collection.hasIndex("firstName")); + assertEquals(collection.size(), 10); + assertEquals(db.listCollectionNames().size(), 1); + assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 2); + db.close(); + + migration = new Migration(2, 3) { + @Override + public void migrate(Instructions instructions) { + instructions.forDatabase() + .changePassword("test-user", "test-password", "password"); + + instructions.forCollection("testCollectionMigrate") + .dropIndex("firstName") + .deleteField("bloodGroup") + .addField("name", document -> faker.name().fullName()) + .addField("address") + .addField("vehicles", 1) + .renameField("age", "ageGroup") + .createIndex(IndexType.NON_UNIQUE, "ageGroup"); + } + }; + + storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(3) + .addMigrations(migration) + .openOrCreate("test-user", "password"); + + collection = db.getCollection("testCollectionMigrate"); + assertEquals(collection.size(), 10); + assertEquals(db.listCollectionNames().size(), 1); + assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 3); + + assertFalse(collection.hasIndex("firstName")); + assertTrue(collection.hasIndex("ageGroup")); + assertEquals(collection.find(where("age").notEq(null)).size(), 0); + } + + @Test(expected = MigrationException.class) + public void testOpenWithoutSchemaVersion() { + NitriteCollection collection = db.getCollection("test"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + + collection.insert(document); + } + db.close(); + + Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { + @Override + public void migrate(Instructions instruction) { + + instruction.forCollection("test") + .rename("testOpenWithoutSchemaVersion") + .deleteField("lastName"); + } + }; + + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testOpenWithoutSchemaVersion"); + assertEquals(collection.size(), 10); + db.close(); + + storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .openOrCreate(); + + collection = db.getCollection("testOpenWithoutSchemaVersion"); + assertEquals(collection.size(), 10); + } + + @Test + public void testDescendingSchema() { + NitriteCollection collection = db.getCollection("test"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + + collection.insert(document); + } + db.close(); + + Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { + @Override + public void migrate(Instructions instruction) { + + instruction.forCollection("test") + .rename("testDescendingSchema") + .deleteField("lastName"); + } + }; + + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testDescendingSchema"); + assertEquals(collection.size(), 10); + db.close(); + + migration = new Migration(2, Constants.INITIAL_SCHEMA_VERSION) { + @Override + public void migrate(Instructions instructions) { + + instructions.forCollection("testDescendingSchema") + .rename("test"); + } + }; + + storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(1) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + db.close(); + } + + @Test + public void testMigrationWithoutVersion() { + NitriteCollection collection = db.getCollection("test"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + + collection.insert(document); + } + db.close(); + + Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { + @Override + public void migrate(Instructions instruction) { + + instruction.forCollection("test") + .rename("testMigrationWithoutVersion") + .deleteField("lastName"); + } + }; + + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testMigrationWithoutVersion"); + assertEquals(collection.size(), 0); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + db.close(); + } + + @Test + public void testWrongSchemaVersionNoMigration() { + NitriteCollection collection = db.getCollection("testWrongSchemaVersionNoMigration"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + + collection.insert(document); + } + db.close(); + + Migration migration = new Migration(1, 2) { + @Override + public void migrate(Instructions instruction) { + + instruction.forCollection("testWrongSchemaVersionNoMigration") + .rename("test") + .deleteField("lastName"); + } + }; + + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testWrongSchemaVersionNoMigration"); + assertEquals(collection.size(), 0); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + db.close(); + + migration = new Migration(2, 3) { + @Override + public void migrate(Instructions instructions) { + instructions.forCollection("test") + .rename("testWrongSchemaVersionNoMigration"); + } + }; + + storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testWrongSchemaVersionNoMigration"); + assertEquals(collection.size(), 0); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + db.close(); + } + + @Test + public void testReOpenAfterMigration() { + NitriteCollection collection = db.getCollection("testReOpenAfterMigration"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + + collection.insert(document); + } + db.close(); + + Migration migration = new Migration(1, 2) { + @Override + public void migrate(Instructions instruction) { + + instruction.forCollection("testReOpenAfterMigration") + .rename("test") + .deleteField("lastName"); + } + }; + + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testReOpenAfterMigration"); + assertEquals(collection.size(), 0); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + db.close(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testReOpenAfterMigration"); + assertEquals(collection.size(), 0); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + db.close(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .openOrCreate(); + + collection = db.getCollection("testReOpenAfterMigration"); + assertEquals(collection.size(), 0); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + } + + @Test + public void testMultipleMigrations() { + NitriteCollection collection = db.getCollection("testMultipleMigrations"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + + collection.insert(document); + } + db.close(); + + Migration migration1 = new Migration(1, 2) { + @Override + public void migrate(Instructions instruction) { + + instruction.forCollection("testMultipleMigrations") + .rename("test"); + } + }; + + Migration migration2 = new Migration(2, 3) { + @Override + public void migrate(Instructions instruction) { + instruction.forCollection("test") + .addField("fullName", "Dummy Name"); + } + }; + + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration1, migration2) + .openOrCreate(); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + assertEquals(collection.find(where("fullName").eq("Dummy Name")).size(), 0); + db.close(); + + Migration migration3 = new Migration(3, 4) { + @Override + public void migrate(Instructions instruction) { + instruction.forCollection("test") + .addField("age", 10); + } + }; + + storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(4) + .addMigrations(migration1, migration2, migration3) + .openOrCreate(); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + assertEquals(collection.find(where("fullName").eq("Dummy Name")).size(), 10); + assertEquals(collection.find(where("age").eq(10)).size(), 10); + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/migrate/NewClass.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/migrate/NewClass.java new file mode 100644 index 000000000..28f0f15db --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/migrate/NewClass.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.migrate; + +import lombok.Data; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.repository.annotations.Entity; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +/** + * @author Anindya Chatterjee + */ +@Data +@Entity(value = "new", indices = { + @Index(value = "familyName", type = IndexType.NON_UNIQUE), + @Index(value = "fullName", type = IndexType.NON_UNIQUE), + @Index(value = "literature.ratings", type = IndexType.NON_UNIQUE), +}) +public class NewClass { + @Id + private Long empId; + private String firstName; + private String familyName; + private String fullName; + private Literature literature; + + + @Data + public static class Literature { + private String text; + private Integer ratings; + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/migrate/OldClass.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/migrate/OldClass.java new file mode 100644 index 000000000..32a687c53 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/migrate/OldClass.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.migrate; + +import lombok.Data; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.repository.annotations.Entity; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +/** + * @author Anindya Chatterjee + */ +@Data +@Entity(value = "old", indices = { + @Index(value = "firstName", type = IndexType.NON_UNIQUE), + @Index(value = "lastName", type = IndexType.NON_UNIQUE), + @Index(value = "literature.text", type = IndexType.FULL_TEXT), + @Index(value = "literature.ratings", type = IndexType.NON_UNIQUE), +}) +public class OldClass { + @Id + private String uuid; + private String empId; + private String firstName; + private String lastName; + private Literature literature; + + + @Data + public static class Literature { + private String text; + private Float ratings; + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/BaseObjectRepositoryTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/BaseObjectRepositoryTest.java new file mode 100644 index 000000000..607403048 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/BaseObjectRepositoryTest.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteBuilder; +import org.dizitart.no2.common.mapper.JacksonMapperModule; +import org.dizitart.no2.integration.repository.data.*; +import org.dizitart.no2.mvstore.MVStoreModule; +import org.dizitart.no2.mvstore.MVStoreModuleBuilder; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collection; +import java.util.UUID; + +import static org.dizitart.no2.filters.Filter.ALL; +import static org.junit.Assert.assertTrue; + +@RunWith(value = Parameterized.class) +public abstract class BaseObjectRepositoryTest { + @Parameterized.Parameter + public boolean inMemory = false; + @Parameterized.Parameter(value = 1) + public boolean isProtected = false; + @Parameterized.Parameter(value = 2) + public boolean isCompressed = false; + @Parameterized.Parameter(value = 3) + public boolean isAutoCommit = false; + @Parameterized.Parameter(value = 4) + public boolean isAutoCompact = false; + protected Nitrite db; + + protected ObjectRepository companyRepository; + protected ObjectRepository employeeRepository; + protected ObjectRepository aObjectRepository; + protected ObjectRepository cObjectRepository; + protected ObjectRepository bookRepository; + + private final String fileName = getRandomTempDbFile(); + + @Rule + public Retry retry = new Retry(3); + + @Parameterized.Parameters(name = "InMemory = {0}, Protected = {1}, " + + "Compressed = {2}, AutoCommit = {3}") + public static Collection data() { + return Arrays.asList(new Object[][]{ + {false, false, false, false, false}, + {false, false, false, true, false}, + {false, false, true, false, false}, + {false, false, true, true, false}, + {false, true, false, false, false}, + {false, true, false, true, false}, + {false, true, true, false, false}, + {false, true, true, true, true}, + {true, false, false, false, true}, + {true, false, false, true, true}, + {true, false, true, false, true}, + {true, false, true, true, true}, + {true, true, false, false, true}, + {true, true, false, true, true}, + {true, true, true, false, true}, + {true, true, true, true, true}, + }); + } + + public static String getRandomTempDbFile() { + String dataDir = System.getProperty("java.io.tmpdir") + File.separator + "nitrite" + File.separator + "data"; + File file = new File(dataDir); + if (!file.exists()) { + assertTrue(file.mkdirs()); + } + return file.getPath() + File.separator + UUID.randomUUID() + ".db"; + } + + @Before + public void setUp() { + openDb(); + + companyRepository = db.getRepository(Company.class); + employeeRepository = db.getRepository(Employee.class); + + aObjectRepository = db.getRepository(ClassA.class); + cObjectRepository = db.getRepository(ClassC.class); + + bookRepository = db.getRepository(Book.class); + + for (int i = 0; i < 10; i++) { + Company company = DataGenerator.generateCompanyRecord(); + companyRepository.insert(company); + Employee employee = DataGenerator.generateEmployee(); + employee.setEmpId((long) i + 1); + employeeRepository.insert(employee); + + aObjectRepository.insert(ClassA.create(i + 50)); + cObjectRepository.insert(ClassC.create(i + 30)); + + Book book = DataGenerator.randomBook(); + bookRepository.insert(book); + } + } + + private void openDb() { + MVStoreModuleBuilder builder = MVStoreModule.withConfig(); + + if (isCompressed) { + builder.compress(true); + } + + if (!isAutoCommit) { + builder.autoCommit(false); + } + + if (!inMemory) { + builder.filePath(fileName); + } + + MVStoreModule storeModule = builder.build(); + NitriteBuilder nitriteBuilder = Nitrite.builder() + .loadModule(new JacksonMapperModule()) + .fieldSeparator(".") + .loadModule(storeModule); + + if (isProtected) { + db = nitriteBuilder.openOrCreate("test-user", "test-password"); + } else { + db = nitriteBuilder.openOrCreate(); + } + } + + @After + public void clear() throws Exception { + if (companyRepository != null && !companyRepository.isDropped()) { + companyRepository.remove(ALL); + } + + if (employeeRepository != null && !employeeRepository.isDropped()) { + employeeRepository.remove(ALL); + } + + if (aObjectRepository != null && !aObjectRepository.isDropped()) { + aObjectRepository.remove(ALL); + } + + if (cObjectRepository != null && !cObjectRepository.isDropped()) { + cObjectRepository.remove(ALL); + } + + if (bookRepository != null && !bookRepository.isDropped()) { + bookRepository.remove(ALL); + } + + if (db != null && !db.isClosed()) { + db.commit(); + db.close(); + } + + if (!inMemory) { + Files.delete(Paths.get(fileName)); + } + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/CustomFieldSeparatorTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/CustomFieldSeparatorTest.java new file mode 100644 index 000000000..5a60bb6ec --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/CustomFieldSeparatorTest.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.common.mapper.JacksonMapperModule; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.mvstore.MVStoreModule; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; +import org.dizitart.no2.repository.annotations.Indices; +import org.dizitart.no2.integration.repository.data.Company; +import org.dizitart.no2.integration.repository.data.Note; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.io.Serializable; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Date; + +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.integration.repository.BaseObjectRepositoryTest.getRandomTempDbFile; +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee + */ +public class CustomFieldSeparatorTest { + private Nitrite db; + private ObjectRepository repository; + private final String fileName = getRandomTempDbFile(); + +// @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + db = Nitrite.builder() + .loadModule(new MVStoreModule(fileName)) + .loadModule(new JacksonMapperModule()) + .fieldSeparator(":") + .openOrCreate(); + repository = db.getRepository(EmployeeForCustomSeparator.class); + } + + @After + public void reset() throws IOException { + (new NitriteConfig()).fieldSeparator("."); + if (db != null && !db.isClosed()) { + db.close(); + } + + if (db != null && !db.isClosed()) { + db.commit(); + db.close(); + } + + Files.delete(Paths.get(fileName)); + } + + @Test + public void testFieldSeparator() { + assertEquals(NitriteConfig.getFieldSeparator(), ":"); + } + + @Test + public void testFindByEmbeddedField() { + EmployeeForCustomSeparator employee = new EmployeeForCustomSeparator(); + employee.setCompany(new Company()); + employee.setEmployeeNote(new Note()); + + employee.setEmpId(123L); + employee.setJoinDate(new Date()); + employee.setBlob(new byte[0]); + employee.setAddress("Dummy address"); + + employee.getCompany().setCompanyId(987L); + employee.getCompany().setCompanyName("Dummy Company"); + employee.getCompany().setDateCreated(new Date()); + + employee.getEmployeeNote().setNoteId(567L); + employee.getEmployeeNote().setText("Dummy Note"); + + repository.insert(employee); + + assertEquals(repository.find(where("employeeNote.text").eq("Dummy Note")).size(), 0); + assertEquals(repository.find(where("employeeNote:text").text("Dummy Note")).size(), 1); + + assertEquals(repository.find(where("company.companyName").eq("Dummy Company")).size(), 0); + assertEquals(repository.find(where("company:companyName").eq("Dummy Company")).size(), 1); + } + + @ToString + @EqualsAndHashCode + @Indices({ + @Index(value = "joinDate", type = IndexType.NON_UNIQUE), + @Index(value = "address", type = IndexType.FULL_TEXT), + @Index(value = "employeeNote:text", type = IndexType.FULL_TEXT) + }) + public static class EmployeeForCustomSeparator implements Serializable { + @Id + @Getter + @Setter + private Long empId; + + @Getter + @Setter + private Date joinDate; + + @Getter + @Setter + private String address; + + @Getter + @Setter + private Company company; + + @Getter + @Setter + private byte[] blob; + + @Getter + @Setter + private Note employeeNote; + + EmployeeForCustomSeparator() { + } + + public EmployeeForCustomSeparator(EmployeeForCustomSeparator copy) { + empId = copy.empId; + joinDate = copy.joinDate; + address = copy.address; + company = copy.company; + blob = copy.blob; + employeeNote = copy.employeeNote; + } + } + +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/FieldProcessorTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/FieldProcessorTest.java new file mode 100644 index 000000000..397876740 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/FieldProcessorTest.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.common.crypto.AESEncryptor; +import org.dizitart.no2.common.crypto.Encryptor; +import org.dizitart.no2.common.processors.Processor; +import org.dizitart.no2.common.processors.StringFieldEncryptionProcessor; +import org.dizitart.no2.exceptions.NitriteSecurityException; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.integration.repository.data.EncryptedPerson; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.nio.charset.StandardCharsets; +import java.util.Date; +import java.util.List; + +import static org.dizitart.no2.common.util.Iterables.toList; +import static org.dizitart.no2.common.util.ObjectUtils.findRepositoryName; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class FieldProcessorTest extends BaseObjectRepositoryTest { + private ObjectRepository persons; + private StringFieldEncryptionProcessor fieldProcessor; + + @Before + public void setUp() { + super.setUp(); + persons = db.getRepository(EncryptedPerson.class); + fieldProcessor = new StringFieldEncryptionProcessor("s3k4e8"); + fieldProcessor.addFields("creditCardNumber", "cvv"); + + EncryptedPerson person = new EncryptedPerson(); + person.setName("John Doe"); + person.setCreditCardNumber("5548960345687452"); + person.setCvv("007"); + person.setExpiryDate(new Date()); + + persons.insert(person); + + persons.addProcessor(fieldProcessor); + + person = new EncryptedPerson(); + person.setName("Jane Doe"); + person.setCreditCardNumber("5500960345687452"); + person.setCvv("008"); + person.setExpiryDate(new Date()); + persons.insert(person); + } + + @Test + public void testFieldEncryptionInNitriteMap() { + NitriteMap nitriteMap = persons.getDocumentCollection().getStore() + .openMap(findRepositoryName(EncryptedPerson.class, null), NitriteId.class, Document.class); + + List documents = toList(nitriteMap.values()); + for (Document document : documents) { + if (document.get("creditCardNumber", String.class).equalsIgnoreCase("5548960345687452")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("creditCardNumber", String.class).equalsIgnoreCase("5500960345687452")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("cvv", String.class).equalsIgnoreCase("008")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("cvv", String.class).equalsIgnoreCase("007")) { + Assert.fail("unencrypted secret text found"); + } + } + } + + @Test + public void testSuccessfulDecryption() { + EncryptedPerson person = persons.find(where("name").eq("Jane Doe")).firstOrNull(); + assertNotNull(person); + + assertEquals(person.getCreditCardNumber(), "5500960345687452"); + assertEquals(person.getCvv(), "008"); + + person = persons.find(where("name").eq("John Doe")).firstOrNull(); + assertNotNull(person); + + assertEquals(person.getCreditCardNumber(), "5548960345687452"); + assertEquals(person.getCvv(), "007"); + } + + @Test(expected = NitriteSecurityException.class) + public void testFailedDecryption() { + ObjectRepository testPersons = db.getRepository(EncryptedPerson.class, "test"); + + Encryptor encryptor = new AESEncryptor("secret"); + Encryptor wrongEncryptor = new AESEncryptor("secret", "AES/GCM/NoPadding", + 5, 5, 5); + + testPersons.addProcessor(new Processor() { + @Override + public Document processBeforeWrite(Document document) { + String creditCardNumber = document.get("creditCardNumber", String.class); + String encryptedCreditCardNumber = encryptor.encrypt(creditCardNumber.getBytes(StandardCharsets.UTF_8)); + document.put("creditCardNumber", encryptedCreditCardNumber); + return document; + } + + @Override + public Document processAfterRead(Document document) { + String encryptedCreditCardNumber = document.get("creditCardNumber", String.class); + String creditCardNumber = wrongEncryptor.decrypt(encryptedCreditCardNumber); + document.put("creditCardNumber", creditCardNumber); + return document; + } + }); + + EncryptedPerson person = new EncryptedPerson(); + person.setName("John Doe"); + person.setCreditCardNumber("5548960345687452"); + person.setCvv("007"); + person.setExpiryDate(new Date()); + + testPersons.insert(person); + + person = new EncryptedPerson(); + person.setName("Jane Doe"); + person.setCreditCardNumber("5500960345687452"); + person.setCvv("008"); + person.setExpiryDate(new Date()); + testPersons.insert(person); + + testPersons.find(where("name").eq("Jane Doe")).firstOrNull(); + } + + @Test + public void testSearchOnEncryptedField() { + EncryptedPerson person = persons.find(where("cvv").eq("008")).firstOrNull(); + assertNull(person); + } + + @Test + public void testUpdateEncryptedField() { + EncryptedPerson person = new EncryptedPerson(); + person.setName("John Doe"); + person.setCreditCardNumber("00000000000000"); + person.setCvv("007"); + person.setExpiryDate(new Date()); + + WriteResult writeResult = persons.update(where("name").eq("John Doe"), person); + assertEquals(writeResult.getAffectedCount(), 1); + + person = persons.find(where("name").eq("John Doe")).firstOrNull(); + assertNotNull(person); + + assertEquals(person.getCreditCardNumber(), "00000000000000"); + assertEquals(person.getCvv(), "007"); + } + + @Test + public void testIndexOnEncryptedField() { + persons.createIndex("cvv"); + EncryptedPerson person = persons.find(where("cvv").eq("008")).firstOrNull(); + assertNull(person); + } + + @Test + public void testRemoveProcessor() { + EncryptedPerson person = persons.find(where("cvv").eq("008")).firstOrNull(); + assertNull(person); + + person = persons.find(where("creditCardNumber").eq("5548960345687452")).firstOrNull(); + assertNull(person); + + persons.removeProcessor(fieldProcessor); + + person = persons.find(where("cvv").eq("008")).firstOrNull(); + assertNotNull(person); + + person = persons.find(where("creditCardNumber").eq("5548960345687452")).firstOrNull(); + assertNotNull(person); + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/InternalClass.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/InternalClass.java new file mode 100644 index 000000000..a437f6c1a --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/InternalClass.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import lombok.Data; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Data +class InternalClass { + @Id + private long id; + private String name; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/NitriteIdAsIdTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/NitriteIdAsIdTest.java new file mode 100644 index 000000000..a7a42681c --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/NitriteIdAsIdTest.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import lombok.Data; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.common.util.Iterables; +import org.dizitart.no2.exceptions.InvalidIdException; +import org.dizitart.no2.common.mapper.JacksonMapper; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Id; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import static org.dizitart.no2.common.module.NitriteModule.module; +import static org.dizitart.no2.integration.repository.BaseObjectRepositoryTest.getRandomTempDbFile; +import static org.dizitart.no2.integration.repository.TestUtil.createDb; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * @author Anindya Chatterjee + */ +public class NitriteIdAsIdTest { + private final String fileName = getRandomTempDbFile(); + private Nitrite db; + private ObjectRepository repo; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void before() { + JacksonMapper mapper = new JacksonMapper(); + db = createDb(fileName, module(mapper)); + repo = db.getRepository(WithNitriteId.class); + } + + @After + public void after() throws IOException { + db.close(); + Files.delete(Paths.get(fileName)); + } + + @Test + public void testNitriteIdField() { + WithNitriteId item1 = new WithNitriteId(); + item1.name = "first"; + + WithNitriteId item2 = new WithNitriteId(); + item2.name = "second"; + + repo.insert(item1, item2); + + Cursor cursor = repo.find(); + for (WithNitriteId withNitriteId : cursor) { + System.out.println(withNitriteId.name); + assertNotNull(withNitriteId.idField); + } + + WithNitriteId withNitriteId = cursor.firstOrNull(); + withNitriteId.name = "third"; + + NitriteId id = withNitriteId.idField; + repo.update(withNitriteId); + + WithNitriteId byId = repo.getById(id); + assertEquals(withNitriteId, byId); + assertEquals(repo.size(), 2); + } + + @Test(expected = InvalidIdException.class) + public void setIdDuringInsert() { + WithNitriteId item1 = new WithNitriteId(); + item1.name = "first"; + item1.idField = NitriteId.newId(); + + repo.insert(item1); + } + + @Test + public void changeIdDuringUpdate() { + WithNitriteId item2 = new WithNitriteId(); + item2.name = "second"; + WriteResult result = repo.insert(item2); + NitriteId nitriteId = Iterables.firstOrNull(result); + WithNitriteId byId = repo.getById(nitriteId); + byId.idField = NitriteId.newId(); + + result = repo.update(byId); + assertEquals(result.getAffectedCount(), 0); + assertEquals(repo.size(), 1); + } + + @Data + private static class WithNitriteId { + @Id + private NitriteId idField; + private String name; + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/ObjectCursorTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/ObjectCursorTest.java new file mode 100644 index 000000000..132746f0e --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/ObjectCursorTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.integration.repository.data.Employee; +import org.junit.Test; + +import java.util.AbstractCollection; +import java.util.Date; + +/** + * @author Anindya Chatterjee + */ +public class ObjectCursorTest extends BaseObjectRepositoryTest { + + @Test(expected = ValidationException.class) + public void testProjectForInterface() { + Cursor cursor = employeeRepository.find(); + cursor.project(Comparable.class); + } + + @Test(expected = ValidationException.class) + public void testProjectForPrimitive() { + Cursor cursor = employeeRepository.find(); + cursor.project(int.class); + } + + @Test(expected = ValidationException.class) + public void testProjectForArray() { + Cursor cursor = employeeRepository.find(); + cursor.project(String[].class); + } + + @Test(expected = ValidationException.class) + public void testProjectForAbstractClass() { + Cursor cursor = employeeRepository.find(); + cursor.project(AbstractCollection.class); + } + + @Test(expected = ValidationException.class) + public void testProjectForValueType() { + Cursor cursor = employeeRepository.find(); + RecordStream project = cursor.project(Date.class); + project.forEach(System.out::println); + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryNegativeTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryNegativeTest.java new file mode 100644 index 000000000..48307a3bd --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryNegativeTest.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.common.mapper.JacksonMapperModule; +import org.dizitart.no2.exceptions.*; +import org.dizitart.no2.integration.repository.data.*; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class ObjectRepositoryNegativeTest { + private final String dbPath = BaseObjectRepositoryTest.getRandomTempDbFile(); + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + db = TestUtil.createDb(dbPath, new JacksonMapperModule()); + } + + @After + public void close() throws IOException { + db.close(); + db = null; + Files.delete(Paths.get(dbPath)); + } + + @Test(expected = ObjectMappingException.class) + public void testWithCircularReference() { + ObjectRepository repository = db.getRepository(WithCircularReference.class); + + WithCircularReference parent = new WithCircularReference(); + parent.setName("parent"); + WithCircularReference object = new WithCircularReference(); + object.setName("test"); + object.setParent(parent); + // circular reference + parent.setParent(object); + + repository.insert(object); + WithCircularReference instance = repository.getById("parent"); + assertEquals(instance.getName(), object.getName()); + assertEquals(instance.getParent().getName(), object.getParent().getName()); + } + + @Test(expected = ObjectMappingException.class) + public void testWithCustomConstructor() { + ObjectRepository repository = db.getRepository(WithCustomConstructor.class); + + WithCustomConstructor object = new WithCustomConstructor("test", 2L); + + repository.insert(object); + WithCustomConstructor instance = repository.getById("test"); + assertEquals(object.getName(), instance.getName()); + assertEquals(object.getNumber(), instance.getNumber()); + } + + @Test(expected = InvalidIdException.class) + public void testWithEmptyStringId() { + ObjectRepository repository = db.getRepository(WithEmptyStringId.class); + WithEmptyStringId object = new WithEmptyStringId(); + object.setName(""); // empty id value + + WriteResult result = repository.insert(object); + for (NitriteId id : result) { + WithEmptyStringId instance = repository.getById(id); + assertEquals(instance, object); + } + } + + @Test(expected = InvalidIdException.class) + public void testWithNullId() { + ObjectRepository repository = db.getRepository(WithNullId.class); + WithNullId object = new WithNullId(); + + WriteResult result = repository.insert(object); + for (NitriteId id : result) { + WithNullId instance = repository.getById(id); + assertEquals(instance, object); + } + } + + @Test(expected = ValidationException.class) + public void testWithValueTypeRepository() { + ObjectRepository repository = db.getRepository(String.class); + repository.insert("test"); + } + + @Test(expected = InvalidOperationException.class) + public void testFindResultRemove() { + ObjectRepository repository = db.getRepository(Employee.class); + repository.insert(DataGenerator.generateEmployee()); + RecordStream result = repository.find(); + result.iterator().remove(); + } + + @Test(expected = IndexingException.class) + public void testWithObjectId() { + ObjectRepository repository = db.getRepository(WithObjectId.class); + WithOutId id = new WithOutId(); + id.setName("test"); + id.setNumber(1); + + WithObjectId object = new WithObjectId(); + object.setWithOutId(id); + repository.insert(object); + } + + @Test(expected = NotIdentifiableException.class) + public void testUpdateNoId() { + ObjectRepository repository = db.getRepository(WithOutId.class); + WithOutId object = new WithOutId(); + object.setName("name"); + object.setNumber(1L); + repository.update(object); + } + + @Test(expected = NotIdentifiableException.class) + public void testRemoveNoId() { + ObjectRepository repository = db.getRepository(WithOutId.class); + WithOutId object = new WithOutId(); + object.setName("name"); + object.setNumber(1L); + repository.remove(object); + } + + @Test(expected = ValidationException.class) + public void testProjectionFailedInstantiate() { + ObjectRepository repository = db.getRepository(WithOutId.class); + WithOutId object = new WithOutId(); + object.setName("name"); + object.setNumber(1L); + repository.insert(object); + + RecordStream project = repository.find().project(NitriteId.class); + assertNull(project.toList()); + } + + @Test(expected = ValidationException.class) + public void testNullInsert() { + ObjectRepository repository = db.getRepository(WithOutId.class); + repository.insert(null); + } + + @Test(expected = InvalidIdException.class) + public void testGetByNullId() { + ObjectRepository repository = db.getRepository(WithPublicField.class); + WithPublicField object = new WithPublicField(); + object.name = "test"; + object.number = 2; + + repository.insert(object); + WithPublicField instance = repository.getById(null); + assertEquals(object.name, instance.name); + assertEquals(object.number, instance.number); + } + + @Test + public void testExternalNitriteId() { + ObjectRepository repository = db.getRepository(WithNitriteId.class); + WithNitriteId obj = new WithNitriteId(); + NitriteId id = NitriteId.createId("1"); + obj.setIdField(id); + obj.setName("testExternalNitriteId"); + WriteResult result = repository.update(obj, true); + + obj = new WithNitriteId(); + id = result.iterator().next(); + obj.setIdField(id); + obj.setName("testExternalNitriteId"); + result = repository.update(obj, true); + assertNotEquals(id.getIdValue(), result.iterator().next().getIdValue()); + } + + @Test(expected = IndexingException.class) + public void testWithoutEmbeddedId() { + ObjectRepository repository = db.getRepository(WithoutEmbeddedId.class); + assertNull(repository); + } + + @Test(expected = InvalidIdException.class) + public void testGetByWrongIdType() { + ObjectRepository repository = db.getRepository(WithPublicField.class); + WithPublicField object = new WithPublicField(); + object.name = "test"; + object.number = 2; + + repository.insert(object); + + NitriteId id = NitriteId.createId("1"); + WithPublicField instance = repository.getById(id); + assertEquals(object.name, instance.name); + assertEquals(object.number, instance.number); + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryTest.java new file mode 100644 index 000000000..86ce57e8b --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryTest.java @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import com.github.javafaker.Faker; +import lombok.Data; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.meta.Attributes; +import org.dizitart.no2.common.mapper.JacksonMapperModule; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.integration.repository.data.*; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Entity; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Date; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.awaitility.Awaitility.await; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class ObjectRepositoryTest { + private final String dbPath = BaseObjectRepositoryTest.getRandomTempDbFile(); + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + db = TestUtil.createDb(dbPath, new JacksonMapperModule()); + } + + @After + public void close() throws IOException { + db.close(); + db = null; + Files.delete(Paths.get(dbPath)); + } + + @Test + public void testWithClassField() { + ObjectRepository repository = db.getRepository(WithClassField.class); + + WithClassField object = new WithClassField(); + object.setName("test"); + object.setClazz(String.class); + + repository.insert(object); + WithClassField instance = repository.getById("test"); + assertEquals(instance.getName(), object.getName()); + assertEquals(instance.getClazz(), object.getClazz()); + } + + @Test + public void testWithFinalField() { + ObjectRepository repository = db.getRepository(WithFinalField.class); + WithFinalField object = new WithFinalField(); + object.setName("test"); + + repository.insert(object); + for (WithFinalField instance : repository.find()) { + assertEquals(object.getName(), instance.getName()); + assertEquals(object.getNumber(), instance.getNumber()); + } + } + + @Test + public void testWithOutGetterSetter() { + ObjectRepository repository = db.getRepository(WithOutGetterSetter.class); + WithOutGetterSetter object = new WithOutGetterSetter(); + + repository.insert(object); + for (WithOutGetterSetter instance : repository.find()) { + assertEquals(object, instance); + } + } + + @Test + public void testWithOutId() { + ObjectRepository repository = db.getRepository(WithOutId.class); + WithOutId object = new WithOutId(); + object.setName("test"); + object.setNumber(2); + + repository.insert(object); + for (WithOutId instance : repository.find()) { + assertEquals(object.getName(), instance.getName()); + assertEquals(object.getNumber(), instance.getNumber()); + } + } + + @Test + public void testWithPublicField() { + ObjectRepository repository = db.getRepository(WithPublicField.class); + WithPublicField object = new WithPublicField(); + object.name = "test"; + object.number = 2; + + repository.insert(object); + WithPublicField instance = repository.getById("test"); + assertEquals(object.name, instance.name); + assertEquals(object.number, instance.number); + } + + @Test + public void testWithTransientField() { + ObjectRepository repository = db.getRepository(WithTransientField.class); + WithTransientField object = new WithTransientField(); + object.setNumber(2); + object.setName("test"); + + repository.insert(object); + WithTransientField instance = repository.getById(2L); + assertNotEquals(object.getName(), instance.getName()); + assertNull(instance.getName()); + assertEquals(object.getNumber(), instance.getNumber()); + } + + @Test + public void testWriteThousandRecords() { + int count = 5000; + + ObjectRepository repository = db.getRepository(StressRecord.class); + + for (int i = 0; i < count; i++) { + StressRecord record = new StressRecord(); + record.setFirstName(UUID.randomUUID().toString()); + record.setFailed(false); + record.setLastName(UUID.randomUUID().toString()); + record.setProcessed(false); + + repository.insert(record); + } + + Cursor cursor + = repository.find(where("failed").eq(false)); + for (StressRecord record : cursor) { + record.setProcessed(true); + repository.update(where("firstName").eq(record.getFirstName()), record); + } + } + + @Test + public void testWithPackagePrivateClass() { + ObjectRepository repository = db.getRepository(InternalClass.class); + InternalClass internalClass = new InternalClass(); + internalClass.setId(1); + internalClass.setName("name"); + + repository.insert(internalClass); + InternalClass instance = repository.getById((long) 1); + assertEquals(internalClass.getName(), instance.getName()); + assertEquals(internalClass.getId(), instance.getId()); + } + + @Test + public void testWithPrivateConstructor() { + ObjectRepository repository = + db.getRepository(WithPrivateConstructor.class); + + WithPrivateConstructor object = WithPrivateConstructor.create("test", 2L); + repository.insert(object); + for (WithPrivateConstructor instance : repository.find()) { + assertEquals(object, instance); + } + } + + @Test + public void testWithDateAsId() { + ObjectRepository repository = db.getRepository(WithDateId.class); + + WithDateId object1 = new WithDateId(); + object1.setId(new Date(1482773634L)); + object1.setName("first date"); + repository.insert(object1); + + WithDateId object2 = new WithDateId(); + object2.setName("second date"); + object2.setId(new Date(1482773720L)); + repository.insert(object2); + + assertEquals(repository.find(where("id").eq(new Date(1482773634L))) + .firstOrNull(), object1); + assertEquals(repository.find(where("id").eq(new Date(1482773720L))) + .firstOrNull(), object2); + } + + @Test + public void testWithIdInheritance() { + ObjectRepository repository = db.getRepository(ChildClass.class); + assertTrue(repository.hasIndex("id")); + assertTrue(repository.hasIndex("date")); + assertTrue(repository.hasIndex("text")); + + ChildClass childClass = new ChildClass(); + childClass.setName("first"); + childClass.setDate(new Date(100000L)); + childClass.setId(1L); + childClass.setText("I am first class"); + repository.insert(childClass); + + childClass = new ChildClass(); + childClass.setName("seconds"); + childClass.setDate(new Date(100001L)); + childClass.setId(2L); + childClass.setText("I am second class"); + repository.insert(childClass); + + childClass = new ChildClass(); + childClass.setName("third"); + childClass.setDate(new Date(100002L)); + childClass.setId(3L); + childClass.setText("I am third class"); + repository.insert(childClass); + + assertEquals(repository.find(where("text").text("class")).size(), 3); + assertEquals(repository.find(where("text").text("second")).size(), 0); // filtered in stop words + assertEquals(repository.find(where("date").eq(new Date(100000L))).size(), 1); + assertEquals(repository.find(where("id").eq(1L)).size(), 1); + } + + @Test + public void testAttributes() { + ObjectRepository repository = db.getRepository(WithDateId.class); + Attributes attributes = new Attributes(repository.getDocumentCollection().getName()); + repository.setAttributes(attributes); + assertEquals(repository.getAttributes(), attributes); + } + + @Test + public void testKeyedRepository() { + // an object repository of employees who are managers + ObjectRepository managerRepo = db.getRepository(Employee.class, "managers"); + + // an object repository of all employee + ObjectRepository employeeRepo = db.getRepository(Employee.class); + + // and object repository of employees who are developers + ObjectRepository developerRepo = db.getRepository(Employee.class, "developers"); + + Employee manager = new Employee(); + manager.setEmpId(1L); + manager.setAddress("abcd"); + manager.setJoinDate(new Date()); + + Employee developer = new Employee(); + developer.setEmpId(2L); + developer.setAddress("xyz"); + developer.setJoinDate(new Date()); + + managerRepo.insert(manager); + employeeRepo.insert(manager, developer); + developerRepo.insert(developer); + + assertTrue(db.hasRepository(Employee.class)); + assertTrue(db.hasRepository(Employee.class, "managers")); + assertTrue(db.hasRepository(Employee.class, "developers")); + + assertEquals(db.listRepositories().size(), 1); + assertEquals(db.listKeyedRepository().size(), 2); + + assertEquals(employeeRepo.find(where("address").text("abcd")).size(), 1); + assertEquals(employeeRepo.find(where("address").text("xyz")).size(), 1); + assertEquals(managerRepo.find(where("address").text("xyz")).size(), 0); + assertEquals(managerRepo.find(where("address").text("abcd")).size(), 1); + assertEquals(developerRepo.find(where("address").text("xyz")).size(), 1); + assertEquals(developerRepo.find(where("address").text("abcd")).size(), 0); + } + + @Test + public void testEntityRepository() { + ObjectRepository managerRepo = db.getRepository(EmployeeEntity.class, "managers"); + ObjectRepository employeeRepo = db.getRepository(EmployeeEntity.class); + ObjectRepository developerRepo = db.getRepository(EmployeeEntity.class, "developers"); + + managerRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); + employeeRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); + developerRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); + + boolean errored = false; + try { + NitriteCollection collection = db.getCollection("entity.employee"); + } catch (ValidationException e) { + errored = true; + } + assertTrue(errored); + + assertTrue(db.listRepositories().contains("entity.employee")); + assertEquals(db.listKeyedRepository().size(), 2); + assertEquals(db.listCollectionNames().size(), 0); + + assertTrue(managerRepo.hasIndex("firstName")); + assertTrue(managerRepo.hasIndex("lastName")); + assertTrue(employeeRepo.hasIndex("lastName")); + assertTrue(employeeRepo.hasIndex("lastName")); + + managerRepo.drop(); + assertEquals(db.listKeyedRepository().size(), 1); + } + + @Test + public void testIssue217() { + ObjectRepository employeeRepo = db.getRepository(EmployeeEntity.class); + AtomicInteger counter = new AtomicInteger(0); + employeeRepo.subscribe(eventInfo -> counter.incrementAndGet()); + + ObjectRepository employeeRepo2 = db.getRepository(EmployeeEntity.class); + employeeRepo2.insert(new EmployeeEntity()); + await().atMost(5, TimeUnit.SECONDS).until(() -> counter.get() == 1); + } + + @Data + @Entity(value = "entity.employee", indices = { + @Index(value = "firstName", type = IndexType.NON_UNIQUE), + @Index(value = "lastName", type = IndexType.NON_UNIQUE), + }) + private static class EmployeeEntity { + private static final Faker faker = new Faker(); + + @Id + private Long id; + private String firstName; + private String lastName; + + public EmployeeEntity() { + id = faker.number().randomNumber(); + firstName = faker.name().firstName(); + lastName = faker.name().lastName(); + } + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/ProjectionTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/ProjectionTest.java new file mode 100644 index 000000000..a384735ad --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/ProjectionTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.dizitart.no2.integration.repository.data.SubEmployee; +import org.junit.Test; + +import java.util.Iterator; + +import static org.dizitart.no2.collection.FindOptions.skipBy; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class ProjectionTest extends BaseObjectRepositoryTest { + + @Test + public void testHasMore() { + RecordStream iterable = employeeRepository.find(skipBy(0).limit(5)) + .project(SubEmployee.class); + assertFalse(iterable.isEmpty()); + } + + @Test + public void testSize() { + RecordStream iterable = employeeRepository.find(skipBy(0).limit(5)) + .project(SubEmployee.class); + assertEquals(iterable.size(), 5); + } + + @Test + public void testToString() { + RecordStream iterable = employeeRepository.find(skipBy(0).limit(5)) + .project(SubEmployee.class); + assertNotNull(iterable.toString()); + } + + @Test(expected = InvalidOperationException.class) + public void testRemove() { + RecordStream iterable = employeeRepository.find(skipBy(0).limit(5)) + .project(SubEmployee.class); + Iterator iterator = iterable.iterator(); + if (iterator.hasNext()) { + iterator.next(); + iterator.remove(); + } + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/RepositoryCompoundIndexTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/RepositoryCompoundIndexTest.java new file mode 100644 index 000000000..9431d991e --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/RepositoryCompoundIndexTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.integration.repository.data.Book; +import org.dizitart.no2.integration.repository.data.BookId; +import org.junit.Test; + +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee + */ +public class RepositoryCompoundIndexTest extends BaseObjectRepositoryTest { + + @Test + public void testFindById() { + BookId bookId = new BookId(); + bookId.setAuthor("John Doe"); + bookId.setIsbn("123456"); + bookId.setName("Nitrite Database"); + + Book book = new Book(); + book.setBookId(bookId); + book.setDescription("Some random book description"); + book.setPrice(22.56); + book.setPublisher("My Publisher House"); + book.setTags(Arrays.asList("database", "nosql")); + + bookRepository.insert(book); + + Book bookById = bookRepository.getById(bookId); + assertEquals(bookById, book); + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/RepositoryFactoryTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/RepositoryFactoryTest.java new file mode 100644 index 000000000..2de2e8915 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/RepositoryFactoryTest.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.*; +import org.dizitart.no2.collection.events.CollectionEventListener; +import org.dizitart.no2.collection.meta.Attributes; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.common.concurrent.LockService; +import org.dizitart.no2.common.mapper.JacksonMapper; +import org.dizitart.no2.common.module.NitriteModule; +import org.dizitart.no2.common.processors.Processor; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.repository.RepositoryFactory; +import org.dizitart.no2.store.NitriteStore; +import org.dizitart.no2.integration.repository.data.Book; +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; + +import java.util.Collection; + +import static org.dizitart.no2.integration.repository.BaseObjectRepositoryTest.getRandomTempDbFile; +import static org.junit.Assert.assertNotNull; + +/** + * @author Anindya Chatterjee + */ +public class RepositoryFactoryTest { + private final String fileName = getRandomTempDbFile(); + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Test + public void testRepositoryFactory() { + RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); + assertNotNull(factory); + } + + @Test(expected = ValidationException.class) + public void testNullType() { + RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); + JacksonMapper mapper = new JacksonMapper(); + db = TestUtil.createDb(fileName, NitriteModule.module(mapper)); + factory.getRepository(db.getConfig(), null, "dummy"); + } + + @Test + public void testNullCollection() { + RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); + JacksonMapper mapper = new JacksonMapper(); + db = TestUtil.createDb(fileName, NitriteModule.module(mapper)); + factory.getRepository(db.getConfig(), Book.class, null); + } + + @Test(expected = ValidationException.class) + public void testNullContext() { + RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); + factory.getRepository(null, Book.class, "dummy"); + } + + @After + public void cleanUp() { + if (db != null && !db.isClosed()) { + db.close(); + } + } + + private static class DummyCollection implements NitriteCollection { + + @Override + public WriteResult insert(Document document, Document... documents) { + return null; + } + + @Override + public WriteResult update(Filter filter, Document update, UpdateOptions updateOptions) { + return null; + } + + @Override + public WriteResult remove(Filter filter, boolean justOne) { + return null; + } + + @Override + public DocumentCursor find() { + return null; + } + + @Override + public DocumentCursor find(Filter filter) { + return null; + } + + @Override + public DocumentCursor find(Filter filter, FindOptions findOptions) { + return null; + } + + @Override + public Document getById(NitriteId nitriteId) { + return null; + } + + @Override + public String getName() { + return null; + } + + @Override + public void addProcessor(Processor processor) { + + } + + @Override + public void removeProcessor(Processor processor) { + + } + + @Override + public void createIndex(IndexOptions indexOptions, String... fields) { + + } + + @Override + public void rebuildIndex(String... fields) { + + } + + @Override + public Collection listIndices() { + return null; + } + + @Override + public boolean hasIndex(String... fields) { + return false; + } + + @Override + public boolean isIndexing(String... fields) { + return false; + } + + @Override + public void dropIndex(String... fields) { + + } + + @Override + public void dropAllIndices() { + + } + + @Override + public WriteResult insert(Document[] elements) { + return null; + } + + @Override + public WriteResult update(Document element, boolean insertIfAbsent) { + return null; + } + + @Override + public WriteResult remove(Document element) { + return null; + } + + @Override + public void clear() { + + } + + @Override + public void drop() { + + } + + @Override + public boolean isDropped() { + return false; + } + + @Override + public boolean isOpen() { + return false; + } + + @Override + public void close() { + + } + + @Override + public long size() { + return 0; + } + + @Override + public NitriteStore getStore() { + return null; + } + + @Override + public void subscribe(CollectionEventListener listener) { + + } + + @Override + public void unsubscribe(CollectionEventListener listener) { + + } + + @Override + public Attributes getAttributes() { + return null; + } + + @Override + public void setAttributes(Attributes attributes) { + + } + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/RepositoryJoinTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/RepositoryJoinTest.java new file mode 100644 index 000000000..ccd66e1dd --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/RepositoryJoinTest.java @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import lombok.Data; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteBuilder; +import org.dizitart.no2.collection.FindOptions; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.Lookup; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.dizitart.no2.common.mapper.JacksonMapperModule; +import org.dizitart.no2.mvstore.MVStoreModule; +import org.dizitart.no2.mvstore.MVStoreModuleBuilder; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Id; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import static org.dizitart.no2.filters.Filter.ALL; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +@RunWith(value = Parameterized.class) +public class RepositoryJoinTest { + @Parameterized.Parameter + public boolean inMemory = false; + @Parameterized.Parameter(value = 1) + public boolean isProtected = false; + @Parameterized.Parameter(value = 2) + public boolean isCompressed = false; + @Parameterized.Parameter(value = 3) + public boolean isAutoCommit = false; + @Parameterized.Parameter(value = 4) + public boolean isAutoCompact = false; + protected Nitrite db; + private final String fileName = BaseObjectRepositoryTest.getRandomTempDbFile(); + private ObjectRepository personRepository; + private ObjectRepository
addressRepository; + + @Rule + public Retry retry = new Retry(3); + + @Parameterized.Parameters(name = "InMemory = {0}, Protected = {1}, " + + "Compressed = {2}, AutoCommit = {3}, AutoCompact = {4}") + public static Collection data() { + return Arrays.asList(new Object[][]{ + {false, false, false, false, false}, + {false, false, false, true, false}, + {false, false, true, false, false}, + {false, false, true, true, false}, + {false, true, false, false, false}, + {false, true, false, true, false}, + {false, true, true, false, false}, + {false, true, true, true, true}, + {true, false, false, false, true}, + {true, false, false, true, true}, + {true, false, true, false, true}, + {true, false, true, true, true}, + {true, true, false, false, true}, + {true, true, false, true, true}, + {true, true, true, false, true}, + {true, true, true, true, true}, + }); + } + + @Before + public void setUp() { + openDb(); + + personRepository = db.getRepository(Person.class); + addressRepository = db.getRepository(Address.class); + + for (int i = 0; i < 10; i++) { + Person person = new Person(); + person.setId(Integer.toString(i)); + person.setName("Person " + i); + personRepository.insert(person); + + Address address = new Address(); + address.setPersonId(Integer.toString(i)); + address.setStreet("Street address " + i); + addressRepository.insert(address); + + if (i == 5) { + Address address2 = new Address(); + address2.setPersonId(Integer.toString(i)); + address2.setStreet("Street address 2nd " + i); + addressRepository.insert(address2); + } + } + } + + private void openDb() { + MVStoreModuleBuilder builder = MVStoreModule.withConfig(); + + if (isCompressed) { + builder.compress(true); + } + + if (!isAutoCommit) { + builder.autoCommit(false); + } + + if (!inMemory) { + builder.filePath(fileName); + } + + MVStoreModule storeModule = builder.build(); + NitriteBuilder nitriteBuilder = Nitrite.builder() + .fieldSeparator(".") + .loadModule(storeModule); + + nitriteBuilder.loadModule(new JacksonMapperModule()); + + if (isProtected) { + db = nitriteBuilder.openOrCreate("test-user1", "test-password1"); + } else { + db = nitriteBuilder.openOrCreate(); + } + } + + @After + public void clear() throws IOException { + if (personRepository != null && !personRepository.isDropped()) { + personRepository.remove(ALL); + } + + if (addressRepository != null && !addressRepository.isDropped()) { + addressRepository.remove(ALL); + } + + if (db != null) { + db.commit(); + db.close(); + } + + if (!inMemory) { + Files.delete(Paths.get(fileName)); + } + } + + @Test + public void testJoin() { + Lookup lookup = new Lookup(); + lookup.setLocalField("id"); + lookup.setForeignField("personId"); + lookup.setTargetField("addresses"); + + RecordStream result + = personRepository.find().join(addressRepository.find(), lookup, + PersonDetails.class); + assertEquals(result.size(), 10); + + for (PersonDetails personDetails : result) { + Address[] addresses = personDetails.addresses.toArray(new Address[0]); + if (personDetails.id.equals("5")) { + assertEquals(addresses.length, 2); + } else { + assertEquals(addresses.length, 1); + assertEquals(addresses[0].personId, personDetails.getId()); + } + } + + result = personRepository.find(FindOptions.skipBy(0).limit(5)).join(addressRepository.find(), lookup, + PersonDetails.class); + + assertEquals(result.size(), 5); + assertFalse(result.isEmpty()); + assertNotNull(result.toString()); + } + + @Test(expected = InvalidOperationException.class) + public void testRemove() { + Lookup lookup = new Lookup(); + lookup.setLocalField("id"); + lookup.setForeignField("personId"); + lookup.setTargetField("addresses"); + + RecordStream result + = personRepository.find().join(addressRepository.find(), lookup, + PersonDetails.class); + assertEquals(result.size(), 10); + + Iterator iterator = result.iterator(); + if (iterator.hasNext()) { + iterator.next(); + iterator.remove(); + } + } + + @Data + public static class Person { + @Id + private NitriteId nitriteId; + private String id; + private String name; + } + + @Data + public static class Address { + @Id + private NitriteId nitriteId; + private String personId; + private String street; + } + + @Data + public static class PersonDetails { + @Id + private NitriteId nitriteId; + private String id; + private String name; + private List
addresses; + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/RepositoryModificationTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/RepositoryModificationTest.java new file mode 100644 index 000000000..26c89c680 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/RepositoryModificationTest.java @@ -0,0 +1,655 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.exceptions.InvalidIdException; +import org.dizitart.no2.exceptions.UniqueConstraintException; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.integration.repository.data.*; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.Test; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Date; +import java.util.Locale; + +import static org.awaitility.Awaitility.await; +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class RepositoryModificationTest extends BaseObjectRepositoryTest { + @Test + public void testCreateIndex() { + assertTrue(companyRepository.hasIndex("companyName")); + assertFalse(companyRepository.hasIndex("dateCreated")); + + companyRepository.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "dateCreated"); + assertTrue(companyRepository.hasIndex("dateCreated")); + assertFalse(companyRepository.isIndexing("dateCreated")); + } + + @Test + public void testRebuildIndex() { + companyRepository.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "dateCreated"); + assertFalse(companyRepository.isIndexing("dateCreated")); + + companyRepository.rebuildIndex("dateCreated"); + // rebuild is sync + assertFalse(companyRepository.isIndexing("dateCreated")); + + await().until(() -> !companyRepository.isIndexing("dateCreated")); + } + + @Test + public void testListIndexes() { + Collection indices = companyRepository.listIndices(); + assertEquals(indices.size(), 2); + + companyRepository.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "dateCreated"); + indices = companyRepository.listIndices(); + assertEquals(indices.size(), 3); + } + + @Test + public void testDropIndex() { + testListIndexes(); + companyRepository.dropIndex("dateCreated"); + Collection indices = companyRepository.listIndices(); + assertEquals(indices.size(), 2); + } + + @Test + public void testDropAllIndex() { + testListIndexes(); + companyRepository.dropAllIndices(); + Collection indices = companyRepository.listIndices(); + assertEquals(indices.size(), 0); + } + + @Test + public void testCompanyRecord() { + Cursor cursor = companyRepository.find(); + assertEquals(cursor.size(), 10); + assertFalse(cursor.isEmpty()); + } + + @Test + public void testInsert() { + Company company = DataGenerator.generateCompanyRecord(); + Cursor cursor = companyRepository.find(); + assertEquals(cursor.size(), 10); + + companyRepository.insert(company); + cursor = companyRepository.find(); + assertEquals(cursor.size(), 11); + + Company company1 = DataGenerator.generateCompanyRecord(); + Company company2 = DataGenerator.generateCompanyRecord(); + companyRepository.insert(new Company[]{company1, company2}); + cursor = companyRepository.find(); + assertEquals(cursor.size(), 13); + } + + @Test + public void testUpdateWithFilter() { + employeeRepository.remove(Filter.ALL); + + Employee employee = new Employee(); + employee.setCompany(null); + employee.setAddress("abcd road"); + employee.setBlob(new byte[]{1, 2, 125}); + employee.setEmpId(12L); + employee.setJoinDate(new Date()); + Note empNote = new Note(); + empNote.setNoteId(23L); + empNote.setText("sample text note"); + employee.setEmployeeNote(empNote); + + employeeRepository.insert(employee); + Cursor result = employeeRepository.find(); + assertEquals(result.size(), 1); + for (Employee e : result) { + assertEquals(e.getAddress(), "abcd road"); + } + + Employee updated = new Employee(employee); + updated.setAddress("xyz road"); + WriteResult writeResult = employeeRepository.update(where("empId").eq(12L), updated); + assertEquals(writeResult.getAffectedCount(), 1); + result = employeeRepository.find(); + assertEquals(result.size(), 1); + for (Employee e : result) { + assertEquals(e.getAddress(), "xyz road"); + } + } + + @Test + public void testUpdateWithJustOnceFalse() throws ParseException { + Date joiningDate = new Date(); + prepareUpdateWithOptions(joiningDate); + + SimpleDateFormat simpleDateFormat + = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); + Date newJoiningDate = simpleDateFormat.parse("2012-07-01T16:02:48.440Z"); + + Document updated1 = createDocument(); + updated1.put("joinDate", newJoiningDate); + + WriteResult writeResult + = employeeRepository.update(where("empId").eq(12L), updated1, false); + assertEquals(writeResult.getAffectedCount(), 1); + + Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 1); + result = employeeRepository.find(where("joinDate").eq(newJoiningDate)); + assertEquals(result.size(), 1); + + employeeRepository.remove(Filter.ALL); + prepareUpdateWithOptions(joiningDate); + result = employeeRepository.find(); + assertEquals(result.size(), 2); + + Document update = createDocument(); + update.put("joinDate", newJoiningDate); + + writeResult = employeeRepository.update(where("joinDate").eq(joiningDate), update, false); + assertEquals(writeResult.getAffectedCount(), 2); + + result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 0); + + result = employeeRepository.find(where("joinDate").eq(newJoiningDate)); + assertEquals(result.size(), 2); + } + + @Test + public void testUpsertTrue() { + Date joiningDate = new Date(); + Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 0); + + Employee employee = new Employee(); + employee.setCompany(null); + employee.setAddress("some road"); + employee.setBlob(new byte[]{1, 2, 125}); + employee.setEmpId(12L); + employee.setJoinDate(joiningDate); + Note empNote1 = new Note(); + empNote1.setNoteId(23L); + empNote1.setText("sample text note"); + employee.setEmployeeNote(empNote1); + + WriteResult writeResult + = employeeRepository.update(where("empId").eq(12), employee, true); + assertEquals(writeResult.getAffectedCount(), 1); + + result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 1); + } + + @Test + public void testUpsertFalse() { + Date joiningDate = new Date(); + Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 0); + + Employee employee = new Employee(); + employee.setCompany(null); + employee.setAddress("some road"); + employee.setBlob(new byte[]{1, 2, 125}); + employee.setEmpId(12L); + employee.setJoinDate(joiningDate); + Note empNote1 = new Note(); + empNote1.setNoteId(23L); + empNote1.setText("sample text note"); + employee.setEmployeeNote(empNote1); + + WriteResult writeResult + = employeeRepository.update(where("empId").eq(12), employee, false); + assertEquals(writeResult.getAffectedCount(), 0); + + result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 0); + } + + @Test + public void testDeleteFilterAndWithOutOption() { + Date joiningDate = new Date(); + prepareUpdateWithOptions(joiningDate); + + Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 2); + + WriteResult writeResult = employeeRepository.remove(where("joinDate").eq(joiningDate)); + assertEquals(writeResult.getAffectedCount(), 2); + result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 0); + } + + @Test + public void testDeleteFilterAndWithOption() { + Date joiningDate = new Date(); + prepareUpdateWithOptions(joiningDate); + + Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 2); + + WriteResult writeResult = employeeRepository.remove(where("joinDate").eq(joiningDate), true); + assertEquals(writeResult.getAffectedCount(), 1); + result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 1); + } + + @Test + public void testEmployeeRecord() { + Iterable totalResult = employeeRepository.find(); + int occurrence = 0; + for (Employee employee : totalResult) { + if (employee.getEmployeeNote().getText().toLowerCase().contains("class aptent")) { + occurrence++; + } + } + + Cursor cursor = employeeRepository.find(where("employeeNote.text").text("Class aptent")); + assertEquals(cursor.size(), occurrence); + } + + @Test + public void testUpdateWithOptions() { + Employee employee = employeeRepository.find().firstOrNull(); + + Document update = createDocument(); + update.put("address", "new address"); + + WriteResult writeResult + = employeeRepository.update(where("empId").eq(employee.getEmpId()), update, false); + assertEquals(writeResult.getAffectedCount(), 1); + + Employee byId = employeeRepository.getById(employee.getEmpId()); + assertEquals(byId.getAddress(), "new address"); + assertEquals(byId.getEmpId(), employee.getEmpId()); + + update.put("address", "another address"); + employeeRepository.update(where("empId").eq(employee.getEmpId()), update); + + byId = employeeRepository.getById(employee.getEmpId()); + assertEquals(byId.getAddress(), "another address"); + assertEquals(byId.getEmpId(), employee.getEmpId()); + } + + @Test(expected = InvalidIdException.class) + public void testMultiUpdateWithObject() { + employeeRepository.remove(Filter.ALL); + + Date now = new Date(); + Employee employee1 = new Employee(); + employee1.setEmpId(1L); + employee1.setAddress("abcd"); + employee1.setJoinDate(now); + + Employee employee2 = new Employee(); + employee2.setEmpId(2L); + employee2.setAddress("xyz"); + employee2.setJoinDate(now); + employeeRepository.insert(employee1, employee2); + + Employee update = new Employee(); + update.setAddress("new address"); + + WriteResult writeResult + = employeeRepository.update(where("joinDate").eq(now), update, false); + assertEquals(writeResult.getAffectedCount(), 0); + } + + @Test + public void testUpdateNull() { + Employee employee = employeeRepository.find().firstOrNull(); + Employee newEmployee = new Employee(employee); + newEmployee.setJoinDate(null); + + Employee result = employeeRepository.find(where("empId").eq(employee.getEmpId())).firstOrNull(); + assertNotNull(result.getJoinDate()); + + WriteResult writeResult = employeeRepository.update(newEmployee, false); + assertEquals(writeResult.getAffectedCount(), 1); + + result = employeeRepository.find(where("empId").eq(employee.getEmpId())).firstOrNull(); + assertNull(result.getJoinDate()); + + // update with object filter and item and set id different + } + + @Test + public void testUpdateWithChangedId() { + Employee employee = employeeRepository.find().firstOrNull(); + Long oldId = employee.getEmpId(); + long count = employeeRepository.size(); + + Employee newEmployee = new Employee(employee); + newEmployee.setEmpId(50L); + + Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); + assertNotNull(result.getJoinDate()); + + WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); + assertEquals(writeResult.getAffectedCount(), 1); + + assertEquals(count, employeeRepository.size()); + Cursor cursor = employeeRepository.find(where("empId").eq(oldId)); + assertEquals(cursor.size(), 0); + } + + @Test(expected = InvalidIdException.class) + public void testUpdateWithNullId() { + Employee employee = employeeRepository.find().firstOrNull(); + Long oldId = employee.getEmpId(); + + Employee newEmployee = new Employee(employee); + newEmployee.setEmpId(null); + + Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); + assertNotNull(result.getJoinDate()); + + WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); + assertEquals(writeResult.getAffectedCount(), 1); + } + + @Test(expected = UniqueConstraintException.class) + public void testUpdateWithDuplicateId() { + Employee employee = employeeRepository.find().firstOrNull(); + Long oldId = employee.getEmpId(); + long count = employeeRepository.size(); + + Employee newEmployee = new Employee(employee); + newEmployee.setEmpId(5L); + + Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); + assertNotNull(result.getJoinDate()); + + WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); + assertEquals(writeResult.getAffectedCount(), 1); + + assertEquals(count, employeeRepository.size()); + Cursor cursor = employeeRepository.find(where("empId").eq(oldId)); + assertEquals(cursor.size(), 0); + } + + @Test + public void testUpdateWithObject() { + Employee employee = employeeRepository.find().firstOrNull(); + Employee newEmployee = new Employee(employee); + + Long id = employee.getEmpId(); + String address = employee.getAddress(); + newEmployee.setAddress("new address"); + + WriteResult writeResult = employeeRepository.update(newEmployee); + assertEquals(writeResult.getAffectedCount(), 1); + + Employee emp = employeeRepository.find(where("empId").eq(id)).firstOrNull(); + assertNotEquals(address, emp.getAddress()); + assertEquals(employee.getEmpId(), emp.getEmpId()); + assertEquals(employee.getJoinDate(), emp.getJoinDate()); + assertArrayEquals(employee.getBlob(), emp.getBlob()); + } + + @Test + public void testUpsertWithObject() { + Employee employee = new Employee(); + employee.setCompany(null); + employee.setAddress("some road"); + employee.setBlob(new byte[]{1, 2, 125}); + employee.setEmpId(12L); + employee.setJoinDate(new Date()); + Note empNote = new Note(); + empNote.setNoteId(23L); + empNote.setText("sample text note"); + employee.setEmployeeNote(empNote); + + WriteResult writeResult = employeeRepository.update(employee, false); + assertEquals(writeResult.getAffectedCount(), 0); + writeResult = employeeRepository.update(employee, true); + assertEquals(writeResult.getAffectedCount(), 1); + + Employee emp = employeeRepository.find(where("empId").eq(12L)).firstOrNull(); + assertEquals(emp, employee); + } + + @Test + public void testRemoveObject() { + Employee employee = new Employee(); + employee.setCompany(null); + employee.setAddress("some road"); + employee.setBlob(new byte[]{1, 2, 125}); + employee.setEmpId(12L); + employee.setJoinDate(new Date()); + Note empNote = new Note(); + empNote.setNoteId(23L); + empNote.setText("sample text note"); + employee.setEmployeeNote(empNote); + + long size = employeeRepository.size(); + + employeeRepository.insert(employee); + assertEquals(employeeRepository.size(), size + 1); + + employeeRepository.remove(employee); + assertEquals(employeeRepository.size(), size); + + Employee emp = employeeRepository.find(where("empId").eq(12L)).firstOrNull(); + assertNull(emp); + } + + private void prepareUpdateWithOptions(Date joiningDate) { + employeeRepository.remove(Filter.ALL); + + Employee employee1 = new Employee(); + employee1.setCompany(null); + employee1.setAddress("some road"); + employee1.setBlob(new byte[]{1, 2, 125}); + employee1.setEmpId(12L); + employee1.setJoinDate(joiningDate); + Note empNote1 = new Note(); + empNote1.setNoteId(23L); + empNote1.setText("sample text note"); + employee1.setEmployeeNote(empNote1); + + Employee employee2 = new Employee(); + employee2.setCompany(null); + employee2.setAddress("other road"); + employee2.setBlob(new byte[]{10, 12, 25}); + employee2.setEmpId(2L); + employee2.setJoinDate(joiningDate); + Note empNote2 = new Note(); + empNote2.setNoteId(2L); + empNote2.setText("some random note"); + employee2.setEmployeeNote(empNote2); + + employeeRepository.insert(employee1, employee2); + Cursor result = employeeRepository.find(); + assertEquals(result.size(), 2); + for (Employee e : result.project(Employee.class)) { + assertEquals(e.getJoinDate(), joiningDate); + } + } + + @Test + public void testUpdateWithDoc() { + Note note = new Note(); + note.setNoteId(10L); + note.setText("some note text"); + + Document document = createDocument("address", "some address") + .put("employeeNote", note); + + WriteResult result = employeeRepository.update(Filter.ALL, document); + assertEquals(result.getAffectedCount(), 10); + } + + @Test + public void testDeleteIteratorNPE() { + ObjectRepository notes = db.getRepository(Note.class); + Note one = new Note(); + one.setText("Jane"); + one.setNoteId(1L); + Note two = new Note(); + two.setText("Jill"); + two.setNoteId(2L); + + notes.insert(one, two); + + WriteResult writeResult = notes.remove(where("text").eq("Pete")); + for (NitriteId id : writeResult) { + assertNotNull(id); + } + } + + @Test + public void testDelete() { + ObjectRepository repo = db.getRepository(WithNitriteId.class); + WithNitriteId one = new WithNitriteId(); + one.setName("Jane"); + repo.insert(one); + + WithNitriteId note = repo.find().firstOrNull(); + repo.remove(note); + + assertNull(repo.getById(one.idField)); + } + + /* + * Upsert Use Cases + * + * 1. Object does not exists + * a. if upsert true, it will insert + * b. if upsert false, nothing happens + * 2. Object exists + * a. if upsert true, it will update, old id remains same + * b. if upsert false, it will update, old id remains same + * + * */ + + @Test + public void testUpdateObjectNotExistsUpsertTrue() { + ObjectRepository repo = db.getRepository(InternalClass.class); + InternalClass a = new InternalClass(); + a.setId(1); + a.setName("first"); + repo.insert(a); + + a = new InternalClass(); + a.setId(2); + a.setName("second"); + + // it will insert as new object + repo.update(a, true); + assertEquals(repo.size(), 2); + } + + @Test + public void testUpdateObjectNotExistsUpsertFalse() { + ObjectRepository repo = db.getRepository(InternalClass.class); + InternalClass a = new InternalClass(); + a.setId(1); + a.setName("first"); + repo.insert(a); + + a = new InternalClass(); + a.setId(2); + a.setName("second"); + + // no changes will happen to repository + repo.update(a, false); + assertEquals(repo.size(), 1); + assertEquals(repo.find().firstOrNull().getId(), 1); + assertEquals(repo.find().firstOrNull().getName(), "first"); + } + + @Test + public void testUpdateObjectExistsUpsertTrue() { + ObjectRepository repo = db.getRepository(InternalClass.class); + InternalClass a = new InternalClass(); + a.setId(1); + a.setName("first"); + repo.insert(a); + + a = new InternalClass(); + a.setId(1); + a.setName("second"); + + // update existing object, keep id same + repo.update(a, true); + assertEquals(repo.size(), 1); + assertEquals(repo.find().firstOrNull().getId(), 1); + assertEquals(repo.find().firstOrNull().getName(), "second"); + } + + @Test + public void testUpdateObjectExistsUpsertFalse() { + ObjectRepository repo = db.getRepository(InternalClass.class); + InternalClass a = new InternalClass(); + a.setId(1); + a.setName("first"); + repo.insert(a); + + a = new InternalClass(); + a.setId(1); + a.setName("second"); + + // update existing object, keep id same + repo.update(a, false); + assertEquals(repo.size(), 1); + assertEquals(repo.find().firstOrNull().getId(), 1); + assertEquals(repo.find().firstOrNull().getName(), "second"); + } + + @Test + public void testNestedUpdate() { + Employee employee = employeeRepository.getById(1L); + assertNotNull(employee); + + Note note = employee.getEmployeeNote(); + String text = note.getText(); + assertNotNull(text); + + Document update = createDocument("employeeNote.text", "some updated text"); + WriteResult writeResult = employeeRepository.update(where("empId").eq(1L), update, true); + assertEquals(1, writeResult.getAffectedCount()); + + employee = employeeRepository.getById(1L); + assertNotNull(employee); + + note = employee.getEmployeeNote(); + assertNotNull(note); + assertNotEquals(text, note.getText()); + assertEquals("some updated text", note.getText()); + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/RepositorySearchTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/RepositorySearchTest.java new file mode 100644 index 000000000..d0bb00a1c --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/RepositorySearchTest.java @@ -0,0 +1,581 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import lombok.Getter; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.exceptions.InvalidIdException; +import org.dizitart.no2.exceptions.NotIdentifiableException; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.integration.repository.data.*; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.Test; + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.List; + +import static org.dizitart.no2.collection.FindOptions.orderBy; +import static org.dizitart.no2.collection.FindOptions.skipBy; +import static org.dizitart.no2.filters.Filter.*; +import static org.dizitart.no2.filters.FluentFilter.$; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class RepositorySearchTest extends BaseObjectRepositoryTest { + @Test + public void testFindWithOptions() { + Cursor cursor = employeeRepository.find(skipBy(0).limit(1)); + assertEquals(cursor.size(), 1); + assertNotNull(cursor.firstOrNull()); + } + + @Test + public void testEmployeeProjection() { + List employeeList = employeeRepository.find().toList(); + List subEmployeeList + = employeeRepository.find().project(SubEmployee.class).toList(); + + assertNotNull(employeeList); + assertNotNull(subEmployeeList); + + assertTrue(employeeList.size() > 0); + assertTrue(subEmployeeList.size() > 0); + + assertEquals(employeeList.size(), subEmployeeList.size()); + + for (int i = 0; i < subEmployeeList.size(); i++) { + Employee employee = employeeList.get(i); + SubEmployee subEmployee = subEmployeeList.get(i); + + assertEquals(employee.getEmpId(), subEmployee.getEmpId()); + assertEquals(employee.getJoinDate(), subEmployee.getJoinDate()); + assertEquals(employee.getAddress(), subEmployee.getAddress()); + } + + Cursor cursor = employeeRepository.find(); + assertNotNull(cursor.firstOrNull()); + assertNotNull(cursor.toString()); + assertEquals(cursor.toList().size(), employeeList.size()); + assertNotNull(cursor.firstOrNull()); + assertEquals(cursor.toList().size(), employeeList.size()); + } + + @Test + public void testEmptyResultProjection() { + employeeRepository.remove(ALL); + assertNull(employeeRepository.find().firstOrNull()); + + assertNull(employeeRepository.find(where("empId").eq(-1)) + .firstOrNull()); + } + + @Test + public void testGetById() { + ObjectRepository empRepo = db.getRepository(Employee.class); + Employee e1 = DataGenerator.generateEmployee(); + Employee e2 = DataGenerator.generateEmployee(); + Employee e3 = DataGenerator.generateEmployee(); + Employee e4 = DataGenerator.generateEmployee(); + + e1.setEmpId(1000000L); + e2.setEmpId(2000000L); + e3.setEmpId(3000000L); + e4.setEmpId(4000000L); + + empRepo.insert(e1, e2, e3, e4); + + Employee byId = empRepo.getById(2000000L); + assertEquals(byId, e2); + } + + @Test(expected = NotIdentifiableException.class) + public void testGetByIdNoId() { + ObjectRepository repository = db.getRepository(Note.class); + Note n1 = DataGenerator.randomNote(); + Note n2 = DataGenerator.randomNote(); + Note n3 = DataGenerator.randomNote(); + + n1.setNoteId(1000000L); + n2.setNoteId(2000000L); + n3.setNoteId(3000000L); + + repository.insert(n1, n2, n3); + + repository.getById(2000000L); + } + + @Test(expected = InvalidIdException.class) + public void testGetByIdNullId() { + ObjectRepository empRepo = db.getRepository(Employee.class); + Employee e1 = DataGenerator.generateEmployee(); + Employee e2 = DataGenerator.generateEmployee(); + Employee e3 = DataGenerator.generateEmployee(); + Employee e4 = DataGenerator.generateEmployee(); + + e1.setEmpId(1000000L); + e2.setEmpId(2000000L); + e3.setEmpId(3000000L); + e4.setEmpId(4000000L); + + empRepo.insert(e1, e2, e3, e4); + + empRepo.getById(null); + } + + @Test(expected = InvalidIdException.class) + public void testGetByIdWrongType() { + ObjectRepository empRepo = db.getRepository(Employee.class); + Employee e1 = DataGenerator.generateEmployee(); + Employee e2 = DataGenerator.generateEmployee(); + Employee e3 = DataGenerator.generateEmployee(); + Employee e4 = DataGenerator.generateEmployee(); + + e1.setEmpId(1000000L); + e2.setEmpId(2000000L); + e3.setEmpId(3000000L); + e4.setEmpId(4000000L); + + empRepo.insert(e1, e2, e3, e4); + + Employee byId = empRepo.getById("employee"); + assertNull(byId); + } + + @Test + public void testEqualFilterById() { + Employee employee = employeeRepository.find().firstOrNull(); + long empId = employee.getEmpId(); + Employee emp = employeeRepository.find(where("empId").eq(empId)) + .project(Employee.class).firstOrNull(); + assertEquals(employee, emp); + } + + @Test + public void testEqualFilter() { + Employee employee = employeeRepository.find() + .firstOrNull(); + + Employee emp = employeeRepository.find(where("joinDate").eq(employee.getJoinDate())) + .project(Employee.class) + .firstOrNull(); + assertEquals(employee, emp); + } + + @Test + public void testStringEqualFilter() { + ObjectRepository repository = db.getRepository(ProductScore.class); + + ProductScore object = new ProductScore(); + object.setProduct("test"); + object.setScore(1); + repository.insert(object); + + object = new ProductScore(); + object.setProduct("test"); + object.setScore(2); + repository.insert(object); + + object = new ProductScore(); + object.setProduct("another-test"); + object.setScore(3); + repository.insert(object); + + assertEquals(repository.find(where("product").eq("test")).size(), 2); + } + + @Test + public void testAndFilter() { + Employee emp = employeeRepository.find().firstOrNull(); + + long id = emp.getEmpId(); + String address = emp.getAddress(); + Date joinDate = emp.getJoinDate(); + + Cursor cursor = employeeRepository.find( + and( + where("empId").eq(id), + where("address").regex(address), + where("joinDate").eq(joinDate) + ) + ); + Employee employee = cursor.firstOrNull(); + + assertEquals(emp, employee); + } + + @Test + public void testOrFilter() { + Employee emp = employeeRepository.find().firstOrNull(); + long id = emp.getEmpId(); + + Employee employee = employeeRepository.find( + or( + where("empId").eq(id), + where("address").text("n/a"), + where("joinDate").eq(null) + )).firstOrNull(); + + assertEquals(emp, employee); + } + + @Test + public void testNotFilter() { + Employee emp = employeeRepository.find().firstOrNull(); + long id = emp.getEmpId(); + + Employee employee = employeeRepository.find( + where("empId").eq(id).not()).firstOrNull(); + assertNotEquals(emp, employee); + } + + @Test + public void testGreaterFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Ascending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").gt(id)) + .toList(); + + assertFalse(employeeList.contains(emp)); + assertEquals(employeeList.size(), 9); + } + + @Test + public void testGreaterEqualFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Ascending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").gte(id)) + .toList(); + + assertTrue(employeeList.contains(emp)); + assertEquals(employeeList.size(), 10); + } + + @Test + public void testLesserThanFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Descending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").lt(id)) + .toList(); + + assertFalse(employeeList.contains(emp)); + assertEquals(employeeList.size(), 9); + } + + @Test + public void testLesserEqualFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Descending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").lte(id)) + .toList(); + + assertTrue(employeeList.contains(emp)); + assertEquals(employeeList.size(), 10); + } + + @Test + public void testTextFilter() { + Employee emp = employeeRepository.find().firstOrNull(); + String text = emp.getEmployeeNote().getText(); + + List employeeList = employeeRepository.find(where("employeeNote.text").text(text)) + .toList(); + + assertTrue(employeeList.contains(emp)); + } + + @Test + public void testRegexFilter() { + Cursor employees = employeeRepository.find(); + int count = employees.toList().size(); + + List employeeList = employeeRepository.find(where("emailAddress") + .regex("^[a-zA-Z0-9+_.-]+@[a-zA-Z0-9.-]+$")) + .toList(); + + assertEquals(employeeList.size(), count); + } + + @Test + public void testInFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Descending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").in(id, id - 1, id - 2)) + .toList(); + + assertTrue(employeeList.contains(emp)); + assertEquals(employeeList.size(), 3); + + employeeList = employeeRepository.find(where("empId").in(id - 1, id - 2)).toList(); + assertEquals(employeeList.size(), 2); + } + + @Test + public void testNotInFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Descending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").notIn(id, id - 1, id - 2)) + .toList(); + + assertFalse(employeeList.contains(emp)); + assertEquals(employeeList.size(), 7); + + employeeList = employeeRepository.find(where("empId").notIn(id - 1, id - 2)).toList(); + assertEquals(employeeList.size(), 8); + } + + @Test + public void testElemMatchFilter() { + final ProductScore score1 = new ProductScore("abc", 10); + final ProductScore score2 = new ProductScore("abc", 8); + final ProductScore score3 = new ProductScore("abc", 7); + final ProductScore score4 = new ProductScore("xyz", 5); + final ProductScore score5 = new ProductScore("xyz", 7); + final ProductScore score6 = new ProductScore("xyz", 8); + + ObjectRepository repository = db.getRepository(ElemMatch.class); + ElemMatch e1 = new ElemMatch() {{ + setId(1); + setStrArray(new String[]{"a", "b"}); + setProductScores(new ProductScore[]{score1, score4}); + }}; + ElemMatch e2 = new ElemMatch() {{ + setId(2); + setStrArray(new String[]{"d", "e"}); + setProductScores(new ProductScore[]{score2, score5}); + }}; + ElemMatch e3 = new ElemMatch() {{ + setId(3); + setStrArray(new String[]{"a", "f"}); + setProductScores(new ProductScore[]{score3, score6}); + }}; + + repository.insert(e1, e2, e3); + + List elements = repository.find( + where("productScores").elemMatch( + where("product").eq("xyz") + .and(where("score").gte(8)))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("score").lte(8).not())).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("product").eq("xyz") + .or(where("score").gte(8)))).toList(); + assertEquals(elements.size(), 3); + + elements = repository.find( + where("productScores").elemMatch( + where("product").eq("xyz"))).toList(); + assertEquals(elements.size(), 3); + + elements = repository.find( + where("productScores").elemMatch( + where("score").gte(10))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("score").gt(8))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("score").lt(7))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("score").lte(7))).toList(); + assertEquals(elements.size(), 3); + + elements = repository.find( + where("productScores").elemMatch( + where("score").in(7, 8))).toList(); + assertEquals(elements.size(), 2); + + elements = repository.find( + where("productScores").elemMatch( + where("score").notIn(7, 8))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("product").regex("xyz"))).toList(); + assertEquals(elements.size(), 3); + + elements = repository.find(where("strArray").elemMatch($.eq("a"))).toList(); + assertEquals(elements.size(), 2); + + elements = repository.find( + where("strArray").elemMatch( + $.eq("a") + .or($.eq("f") + .or($.eq("b"))).not())).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find(where("strArray").elemMatch($.gt("e"))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find(where("strArray").elemMatch($.gte("e"))).toList(); + assertEquals(elements.size(), 2); + + elements = repository.find(where("strArray").elemMatch($.lte("b"))).toList(); + assertEquals(elements.size(), 2); + + elements = repository.find(where("strArray").elemMatch($.lt("a"))).toList(); + assertEquals(elements.size(), 0); + + elements = repository.find(where("strArray").elemMatch($.in("a", "f"))).toList(); + assertEquals(elements.size(), 2); + + elements = repository.find(where("strArray").elemMatch($.regex("a"))).toList(); + assertEquals(elements.size(), 2); + } + + @Test + public void testFilterAll() { + ObjectRepository repository = db.getRepository(ElemMatch.class); + Cursor cursor = repository.find(ALL); + assertNotNull(cursor); + assertEquals(cursor.size(), 0); + + repository.insert(new ElemMatch()); + cursor = repository.find(ALL); + assertNotNull(cursor); + assertEquals(cursor.size(), 1); + } + + @Test(expected = FilterException.class) + public void testEqualsOnTextIndex() { + PersonEntity p1 = new PersonEntity("jhonny"); + PersonEntity p2 = new PersonEntity("jhonny"); + PersonEntity p3 = new PersonEntity("jhonny"); + + ObjectRepository repository = db.getRepository(PersonEntity.class); + repository.insert(p1); + repository.insert(p2); + repository.insert(p3); + + List sameNamePeople = repository.find(where("name").eq("jhonny")).toList(); + assertEquals(sameNamePeople.size(), 3); + } + + @Test + public void testIssue62() { + PersonEntity p1 = new PersonEntity("abcd"); + p1.setStatus("Married"); + + PersonEntity p2 = new PersonEntity("efgh"); + p2.setStatus("Married"); + + PersonEntity p3 = new PersonEntity("ijkl"); + p3.setStatus("Un-Married"); + + ObjectRepository repository = db.getRepository(PersonEntity.class); + repository.insert(p1); + repository.insert(p2); + repository.insert(p3); + + Filter married = where("status").eq("Married"); + + assertEquals(repository.find(married).size(), 2); + assertEquals(repository.find(married, orderBy("status", SortOrder.Descending)).size(), 2); + + assertEquals(repository.find(orderBy("status", SortOrder.Descending)).firstOrNull().getStatus(), "Un-Married"); + + assertEquals(repository.find(orderBy("status", SortOrder.Ascending)).size(), 3); + assertEquals(repository.find(orderBy("status", SortOrder.Ascending)).firstOrNull().getStatus(), "Married"); + } + + @Test + public void testRepeatableIndexAnnotation() { + ObjectRepository repo = db.getRepository(RepeatableIndexTest.class); + RepeatableIndexTest first = new RepeatableIndexTest(); + first.setAge(12); + first.setFirstName("fName"); + first.setLastName("lName"); + repo.insert(first); + + assertTrue(repo.hasIndex("firstName")); + assertTrue(repo.hasIndex("age")); + assertTrue(repo.hasIndex("lastName")); + + assertEquals(repo.find(where("age").eq(12)).firstOrNull(), first); + } + + @Test + public void testIdSet() { + Cursor employees = employeeRepository.find(orderBy("empId", SortOrder.Ascending)); + assertEquals(employees.size(), 10); + } + + @Test + public void testBetweenFilter() { + @Getter + class TestData { + private final Date age; + + public TestData(Date age) { + this.age = age; + } + } + + TestData data1 = new TestData(new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime()); + TestData data2 = new TestData(new GregorianCalendar(2021, Calendar.FEBRUARY, 12).getTime()); + TestData data3 = new TestData(new GregorianCalendar(2022, Calendar.MARCH, 13).getTime()); + TestData data4 = new TestData(new GregorianCalendar(2023, Calendar.APRIL, 14).getTime()); + TestData data5 = new TestData(new GregorianCalendar(2024, Calendar.MAY, 15).getTime()); + TestData data6 = new TestData(new GregorianCalendar(2025, Calendar.JUNE, 16).getTime()); + + ObjectRepository repository = db.getRepository(TestData.class); + repository.insert(data1, data2, data3, data4, data5, data6); + + Cursor cursor = repository.find(where("age").between( + new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), + new GregorianCalendar(2025, Calendar.JUNE, 16).getTime())); + assertEquals(cursor.size(), 6); + + cursor = repository.find(where("age").between( + new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), + new GregorianCalendar(2025, Calendar.JUNE, 16).getTime(), false)); + assertEquals(cursor.size(), 4); + + cursor = repository.find(where("age").between( + new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), + new GregorianCalendar(2025, Calendar.JUNE, 16).getTime(), false, true)); + assertEquals(cursor.size(), 5); + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/Retry.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/Retry.java new file mode 100644 index 000000000..7c2c065bd --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/Retry.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * @author Anindya Chatterjee + */ +public class Retry implements TestRule { + private final int retryCount; + + public Retry(int retryCount) { + this.retryCount = retryCount; + } + + public Statement apply(Statement base, Description description) { + return statement(base, description); + } + + private Statement statement(final Statement base, final Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + Throwable caughtThrowable = null; + + // implement retry logic here + for (int i = 0; i < retryCount; i++) { + try { + base.evaluate(); + return; + } catch (Throwable t) { + caughtThrowable = t; + System.err.println(description.getDisplayName() + ": run " + (i + 1) + " failed"); + } + } + System.err.println(description.getDisplayName() + ": giving up after " + retryCount + " failures"); + throw caughtThrowable; + } + }; + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/TestUtil.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/TestUtil.java new file mode 100644 index 000000000..6967e6289 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/TestUtil.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import lombok.extern.slf4j.Slf4j; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.common.module.NitriteModule; +import org.dizitart.no2.mvstore.MVStoreModule; + +/** + * @author Anindya Chatterjee + */ +@Slf4j +public class TestUtil { + + public static Nitrite createDb(NitriteModule module) { + MVStoreModule storeModule = MVStoreModule.withConfig() + .build(); + + return Nitrite.builder() + .loadModule(storeModule) + .loadModule(module) + .fieldSeparator(".") + .openOrCreate(); + } + + public static Nitrite createDb(String user, String password, NitriteModule module) { + MVStoreModule storeModule = MVStoreModule.withConfig() + .build(); + + return Nitrite.builder() + .loadModule(storeModule) + .loadModule(module) + .fieldSeparator(".") + .openOrCreate(user, password); + } + + public static Nitrite createDb(String filePath, NitriteModule module) { + return Nitrite.builder() + .loadModule(new MVStoreModule(filePath)) + .loadModule(module) + .fieldSeparator(".") + .openOrCreate(); + } + + public static Nitrite createDb(String filePath, String user, String password, NitriteModule module) { + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(filePath) + .compress(true) + .build(); + + return Nitrite.builder() + .loadModule(storeModule) + .loadModule(module) + .fieldSeparator(".") + .openOrCreate(user, password); + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/UnAnnotatedObjectTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/UnAnnotatedObjectTest.java new file mode 100644 index 000000000..734a55e29 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/UnAnnotatedObjectTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.integration.repository.data.ClassA; +import org.dizitart.no2.integration.repository.data.ClassC; +import org.junit.Test; + +import static org.dizitart.no2.collection.FindOptions.orderBy; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +/** + * @author Anindya Chatterjee. + */ +public class UnAnnotatedObjectTest extends BaseObjectRepositoryTest { + + @Test + public void testFind() { + Cursor cursor = aObjectRepository.find(); + assertEquals(cursor.size(), 10); + assertFalse(cursor.isEmpty()); + + aObjectRepository.createIndex("b.number"); + + cursor = aObjectRepository.find(where("b.number").eq(160).not(), + orderBy("b.number", SortOrder.Ascending).skip(0).limit(10)); + + System.out.println("Available - " + !cursor.isEmpty()); + System.out.println("Total Size - " + cursor.size()); + + Iterable findRecord = cursor.project(ClassA.class); + for (ClassA classA : findRecord) { + System.out.println(classA); + } + + cursor = aObjectRepository.find(where("b.number").eq(160).not(), + orderBy("b.number", SortOrder.Descending).skip(2).limit(7)); + + System.out.println("Available - " + !cursor.isEmpty()); + System.out.println("Total Size - " + cursor.size()); + + findRecord = cursor.project(ClassA.class); + for (ClassA classA : findRecord) { + System.out.println(classA); + } + + cursor = cObjectRepository.find(where("id").gt(900), + orderBy("id", SortOrder.Descending).skip(2).limit(7)); + System.out.println("Available - " + !cursor.isEmpty()); + System.out.println("Total Size - " + cursor.size()); + + Iterable findRecordC = cursor.project(ClassC.class); + for (ClassC classC : findRecordC) { + System.out.println(classC); + } + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/UniversalTextTokenizerTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/UniversalTextTokenizerTest.java new file mode 100644 index 000000000..fac81c611 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/UniversalTextTokenizerTest.java @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteBuilder; +import org.dizitart.no2.common.mapper.JacksonMapperModule; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.index.NitriteTextIndexer; +import org.dizitart.no2.index.fulltext.Languages; +import org.dizitart.no2.index.fulltext.UniversalTextTokenizer; +import org.dizitart.no2.mvstore.MVStoreModule; +import org.dizitart.no2.mvstore.MVStoreModuleBuilder; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Index; +import org.dizitart.no2.repository.annotations.Indices; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.nio.file.Files; +import java.nio.file.Paths; + +import static org.dizitart.no2.common.module.NitriteModule.module; +import static org.dizitart.no2.filters.Filter.ALL; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +/** + * @author Anindya Chatterjee + */ +public class UniversalTextTokenizerTest extends BaseObjectRepositoryTest { + private final String fileName = getRandomTempDbFile(); + private ObjectRepository textRepository; + + @Before + @Override + public void setUp() { + openDb(); + + textRepository = db.getRepository(TextData.class); + + for (int i = 0; i < 10; i++) { + TextData data = new TextData(); + data.id = i; + if (i % 2 == 0) { + data.text = "তারা বলল, “এস আমরা আমাদের জন্যে এক বড় শহর বানাই| আর এমন একটি উঁচু স্তম্ভ বানাই " + + "যা আকাশ স্পর্শ করবে| তাহলে আমরা বিখ্যাত হব এবং এটা আমাদের এক সঙ্গে ধরে রাখবে| সারা পৃথিবীতে " + + "আমরা ছড়িয়ে থাকব না|”"; + } else if (i % 3 == 0) { + data.text = "部汁楽示時葉没式将場参右属。覧観将者雄日語山銀玉襲政著約域費。新意虫跡更味株付安署審完顔団。" + + "困更表転定一史賀面政巣迎文学豊税乗。白間接特時京転閉務講封新内。側流効表害場測投活聞秀職探画労。" + + "福川順式極木注美込行警検直性禁遅。土一詳非物質紙姿漢人内池銀周街躍澹二。平討聞述並時全経詳業映回作朝送恵時。"; + } else if (i % 5 == 0) { + data.text = " أقبل لسفن العالم، في أما, بـ بال أملاً الثالث،. الذود بالرّد الثالث، مع" + + " قام, كردة الضغوط الإمداد أن وصل. ٠٨٠٤ عُقر انتباه يكن قد, أن زهاء وفنلندا بال. لان ما يقوم المعاهدات," + + " بـ بخطوط استعملت عدد. صفحة لفشل ولاتّساع لم قام, في مكثّفة الكونجرس جعل, الثالث، واقتصار دون ان.\n"; + } else { + data.text = "Lorem ipsum dolor sit amet, nobis audire perpetua eu sea. Te semper causae " + + "efficiantur per. Qui affert dolorum at. Mel tale constituto interesset in."; + } + textRepository.insert(data); + } + } + + @After + @Override + public void clear() throws Exception { + if (textRepository != null && !textRepository.isDropped()) { + textRepository.remove(ALL); + } + + if (db != null) { + db.commit(); + db.close(); + } + + if (!inMemory) { + Files.delete(Paths.get(fileName)); + } + } + + private void openDb() { + MVStoreModuleBuilder builder = MVStoreModule.withConfig(); + + if (isCompressed) { + builder.compress(true); + } + + if (!isAutoCommit) { + builder.autoCommit(false); + } + + if (!inMemory) { + builder.filePath(fileName); + } + + MVStoreModule storeModule = builder.build(); + NitriteBuilder nitriteBuilder = Nitrite.builder() + .fieldSeparator(".") + .loadModule(storeModule); + + nitriteBuilder.loadModule(new JacksonMapperModule()); + + UniversalTextTokenizer tokenizer; + if (isCompressed) { + tokenizer = new UniversalTextTokenizer(Languages.Bengali, Languages.Chinese, Languages.English); + } else { + tokenizer = new UniversalTextTokenizer(Languages.ALL); + } + nitriteBuilder.loadModule(module(new NitriteTextIndexer(tokenizer))); + + if (isProtected) { + db = nitriteBuilder.openOrCreate("test-user", "test-password"); + } else { + db = nitriteBuilder.openOrCreate(); + } + } + + @Test + public void testUniversalFullTextIndexing() { + Cursor cursor = textRepository.find(where("text").text("Lorem")); + assertEquals(cursor.size(), 2); + for (TextData data : cursor) { + System.out.println("Id for English text -> " + data.id); + if (data.id % 2 == 0 || data.id % 3 == 0 || data.id % 5 == 0) { + fail(); + } + } + + cursor = textRepository.find(where("text").text("শহর")); + assertEquals(cursor.size(), 5); + for (TextData data : cursor) { + System.out.println("Id for Bengali text -> " + data.id); + if (data.id % 2 != 0) { + fail(); + } + } + + cursor = textRepository.find(where("text").text("転閉")); + assertEquals(cursor.size(), 0); + cursor = textRepository.find(where("text").text("*転閉*")); + assertEquals(cursor.size(), 2); + for (TextData data : cursor) { + System.out.println("Id for Chinese text -> " + data.id); + if (data.id % 3 != 0) { + fail(); + } + } + + cursor = textRepository.find(where("text").text("أقبل")); + if (isCompressed) { + assertEquals(cursor.size(), 1); + for (TextData data : cursor) { + System.out.println("Id for Arabic text -> " + data.id); + if (data.id % 5 != 0) { + fail(); + } + } + } else { + // أقبل eliminated as stop word + assertEquals(cursor.size(), 0); + } + } + + @Indices( + @Index(value = "text", type = IndexType.FULL_TEXT) + ) + public static class TextData { + public int id; + public String text; + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/Book.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/Book.java new file mode 100644 index 000000000..5bffe69e8 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/Book.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.repository.annotations.Entity; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +import java.util.List; + +/** + * @author Anindya Chatterjee + */ +@Data +@Entity(value = "books", indices = { + @Index(value = "tags", type = IndexType.NON_UNIQUE), + @Index(value = "description", type = IndexType.FULL_TEXT), + @Index(value = { "price", "publisher" }) +}) +public class Book { + @JsonProperty("book_id") + @Id(fieldName = "book_id") + private BookId bookId; + + private String publisher; + + private Double price; + + private List tags; + + private String description; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/BookId.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/BookId.java new file mode 100644 index 000000000..988908919 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/BookId.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.dizitart.no2.repository.annotations.Embedded; + +/** + * @author Anindya Chatterjee + */ +@Data +public class BookId { + @Embedded(order = 0) + private String isbn; + + @Embedded(order = 1, fieldName = "book_name") + @JsonProperty("book_name") + private String name; + + private String author; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ChildClass.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ChildClass.java new file mode 100644 index 000000000..7df72c261 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ChildClass.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.repository.annotations.InheritIndices; + +/** + * @author Anindya Chatterjee + */ +@Getter +@Setter +@InheritIndices +public class ChildClass extends ParentClass { + private String name; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ClassA.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ClassA.java new file mode 100644 index 000000000..10aa57a6d --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ClassA.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.util.UUID; + +@EqualsAndHashCode +@ToString +public class ClassA { + @Getter + @Setter + private ClassB b; + @Getter + @Setter + private UUID uid; + @Getter + @Setter + private String string; + @Getter + @Setter + private byte[] blob; + + public static ClassA create(int seed) { + ClassB classB = ClassB.create(seed); + ClassA classA = new ClassA(); + classA.b = classB; + classA.uid = new UUID(seed, seed + 50); + classA.string = Integer.toHexString(seed); + classA.blob = new byte[]{(byte) seed}; + return classA; + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ClassB.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ClassB.java new file mode 100644 index 000000000..567c99244 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ClassB.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@EqualsAndHashCode +@ToString +class ClassB implements Comparable { + @Getter + @Setter + private int number; + @Getter + @Setter + private String text; + + static ClassB create(int seed) { + ClassB classB = new ClassB(); + classB.setNumber(seed + 100); + classB.setText(Integer.toBinaryString(seed)); + return classB; + } + + @Override + public int compareTo(ClassB o) { + return Integer.compare(number, o.number); + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ClassC.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ClassC.java new file mode 100644 index 000000000..237f3f835 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ClassC.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@EqualsAndHashCode +@ToString +public class ClassC { + @Getter + @Setter + private long id; + @Getter + @Setter + private double digit; + @Getter + @Setter + private ClassA parent; + + public static ClassC create(int seed) { + ClassC classC = new ClassC(); + classC.id = seed * 5000; + classC.digit = seed * 69.65; + classC.parent = ClassA.create(seed); + return classC; + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/Company.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/Company.java new file mode 100644 index 000000000..4a85b5156 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/Company.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; +import org.dizitart.no2.repository.annotations.Indices; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +@ToString +@EqualsAndHashCode +@Indices({ + @Index(value = "companyName") +}) +public class Company implements Serializable { + @Id(fieldName = "company_id") + @JsonProperty("company_id") + private Long companyId; + private String companyName; + private Date dateCreated; + private List departments; + private Map> employeeRecord; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/DataGenerator.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/DataGenerator.java new file mode 100644 index 000000000..26e0dcf4a --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/DataGenerator.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import com.github.javafaker.Faker; +import lombok.val; + +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author Anindya Chatterjee. + */ +public class DataGenerator { + private static final Random random = new Random(System.currentTimeMillis()); + private static final AtomicInteger counter = new AtomicInteger(random.nextInt()); + private static final Faker faker = new Faker(random); + + private DataGenerator() {} + + public static Company generateCompanyRecord() { + Company company = new Company(); + company.setCompanyId(System.nanoTime() + counter.incrementAndGet()); + company.setCompanyName(faker.company().name()); + company.setDateCreated(faker.date().past(10, TimeUnit.DAYS)); + List departments = departments(); + company.setDepartments(departments); + + Map> employeeRecord = new HashMap<>(); + for (String department : departments) { + employeeRecord.put(department, + generateEmployeeRecords(company, random.nextInt(20))); + } + company.setEmployeeRecord(employeeRecord); + return company; + } + + private static List generateEmployeeRecords(Company company, int count) { + List employeeList = new ArrayList<>(); + for (int i = 0; i < count; i++) { + Employee employee = generateEmployee(); + employee.setCompany(company); + employeeList.add(employee); + } + return employeeList; + } + + public static Employee generateEmployee() { + Employee employee = new Employee(); + employee.setEmpId(System.nanoTime() + counter.incrementAndGet()); + employee.setJoinDate(faker.date().birthday()); + employee.setAddress(faker.address().fullAddress()); + + employee.setBlob(faker.lorem().paragraph().getBytes(StandardCharsets.UTF_8)); + employee.setEmployeeNote(randomNote()); + employee.setEmailAddress(faker.internet().emailAddress()); + + return employee; + } + + public static Note randomNote() { + Note note = new Note(); + note.setNoteId(System.nanoTime() + counter.incrementAndGet()); + note.setText(faker.lorem().paragraph()); + return note; + } + + public static Book randomBook() { + BookId bookId = new BookId(); + val bookFaker = faker.book(); + bookId.setIsbn(faker.idNumber().ssnValid()); + bookId.setAuthor(bookFaker.author()); + bookId.setName(bookFaker.title()); + + Book book = new Book(); + book.setBookId(bookId); + book.setDescription(faker.backToTheFuture().quote()); + book.setPrice(faker.number().randomDouble(2, 100, 500)); + book.setPublisher(bookFaker.publisher()); + List tags = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + tags.add(bookFaker.genre()); + } + book.setTags(tags); + return book; + } + + private static List departments() { + return new ArrayList() {{ + add("dev"); + add("hr"); + add("qa"); + add("dev-ops"); + add("sales"); + add("marketing"); + add("design"); + add("support"); + }}; + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ElemMatch.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ElemMatch.java new file mode 100644 index 000000000..9de46c3a4 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ElemMatch.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; + +/** + * @author Anindya Chatterjee + */ +@Data +public class ElemMatch { + private long id; + private String[] strArray; + private ProductScore[] productScores; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/Employee.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/Employee.java new file mode 100644 index 000000000..ed048f2e6 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/Employee.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author Anindya Chatterjee. + */ +@ToString +@EqualsAndHashCode +@Index(value = "joinDate", type = IndexType.NON_UNIQUE) +@Index(value = "address", type = IndexType.FULL_TEXT) +@Index(value = "employeeNote.text", type = IndexType.FULL_TEXT) +public class Employee implements Serializable { + @Id + @Getter + @Setter + private Long empId; + + @Getter + @Setter + private Date joinDate; + + @Getter + @Setter + private String address; + + @Getter + @Setter + private String emailAddress; + + @Getter + @Setter + private transient Company company; + + @Getter + @Setter + private byte[] blob; + + @Getter + @Setter + private Note employeeNote; + + public Employee() { + } + + public Employee(Employee copy) { + empId = copy.empId; + joinDate = copy.joinDate; + address = copy.address; + company = copy.company; + blob = copy.blob; + employeeNote = copy.employeeNote; + emailAddress = copy.emailAddress; + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/EncryptedPerson.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/EncryptedPerson.java new file mode 100644 index 000000000..fcf5e7cd6 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/EncryptedPerson.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.repository.annotations.Entity; + +import java.util.Date; + +/** + * @author Anindya Chatterjee + */ +@Data +@Entity +public class EncryptedPerson { + private String name; + private String creditCardNumber; + private String cvv; + private Date expiryDate; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/Note.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/Note.java new file mode 100644 index 000000000..647776b0f --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/Note.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +import java.io.Serializable; + +/** + * @author Anindya Chatterjee. + */ +@EqualsAndHashCode +public class Note implements Serializable { + @Getter + @Setter + private Long noteId; + @Getter + @Setter + private String text; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ParentClass.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ParentClass.java new file mode 100644 index 000000000..844e39223 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ParentClass.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +import java.util.Date; + +/** + * @author Anindya Chatterjee + */ +@Getter +@Setter +@Index(value = "date") +public class ParentClass extends SuperDuperClass { + @Id + protected Long id; + private Date date; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/PersonEntity.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/PersonEntity.java new file mode 100644 index 000000000..cc871a260 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/PersonEntity.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.repository.annotations.Entity; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +import java.util.Date; +import java.util.UUID; + +/** + * @author Anindya Chatterjee + */ +@Data +@Entity(value = "MyPerson", indices = { + @Index(value = "name", type = IndexType.FULL_TEXT), + @Index(value = "status", type = IndexType.NON_UNIQUE) +}) +public class PersonEntity { + @Id + private String uuid; + private String name; + private String status; + private PersonEntity friend; + private Date dateCreated; + + public PersonEntity() { + this.uuid = UUID.randomUUID().toString(); + this.dateCreated = new Date(); + } + + public PersonEntity(String name) { + this.uuid = UUID.randomUUID().toString(); + this.name = name; + this.dateCreated = new Date(); + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ProductScore.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ProductScore.java new file mode 100644 index 000000000..c796a49d3 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/ProductScore.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; + +/** + * @author Anindya Chatterjee + */ +@Getter +@Setter +public class ProductScore { + private String product; + private int score; + + public ProductScore() { + } + + public ProductScore(String product, int score) { + this.product = product; + this.score = score; + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/RepeatableIndexTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/RepeatableIndexTest.java new file mode 100644 index 000000000..a56a63b56 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/RepeatableIndexTest.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.repository.annotations.Index; + +/** + * @author Anindya Chatterjee + */ +@Data +@Index(value = "firstName") +@Index(value = "age", type = IndexType.NON_UNIQUE) +@Index(value = "lastName", type = IndexType.FULL_TEXT) +public class RepeatableIndexTest { + private String firstName; + private Integer age; + private String lastName; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/StressRecord.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/StressRecord.java new file mode 100644 index 000000000..9ab3c6d10 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/StressRecord.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class StressRecord { + private String firstName; + private boolean processed; + private String lastName; + private boolean failed; + private String notes; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/SubEmployee.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/SubEmployee.java new file mode 100644 index 000000000..0b4713a03 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/SubEmployee.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +/** + * @author Anindya Chatterjee. + */ +@EqualsAndHashCode +public class SubEmployee { + @Getter + @Setter + private Long empId; + + @Getter + @Setter + private Date joinDate; + + @Getter + @Setter + private String address; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/SuperDuperClass.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/SuperDuperClass.java new file mode 100644 index 000000000..d39ddf146 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/SuperDuperClass.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.repository.annotations.Index; + +/** + * @author Anindya Chatterjee + */ +@Getter +@Setter +@Index(value = "text", type = IndexType.FULL_TEXT) +public class SuperDuperClass { + private String text; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithCircularReference.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithCircularReference.java new file mode 100644 index 000000000..ef9128b30 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithCircularReference.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithCircularReference { + @Id + private String name; + private WithCircularReference parent; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithClassField.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithClassField.java new file mode 100644 index 000000000..648f562d0 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithClassField.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithClassField { + @Id + private String name; + private Class clazz; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithCustomConstructor.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithCustomConstructor.java new file mode 100644 index 000000000..5982ee0e1 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithCustomConstructor.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithCustomConstructor { + @Id + private String name; + private long number; + + public WithCustomConstructor(String name, long number) { + this.name = name; + this.number = number; + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithDateId.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithDateId.java new file mode 100644 index 000000000..1ad510072 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithDateId.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +/** + * @author Anindya Chatterjee + */ +@Getter +@Setter +@EqualsAndHashCode +public class WithDateId { + private Date id; + private String name; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithEmptyStringId.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithEmptyStringId.java new file mode 100644 index 000000000..cb32a0d84 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithEmptyStringId.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithEmptyStringId { + @Id + private String name; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithFinalField.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithFinalField.java new file mode 100644 index 000000000..43e903151 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithFinalField.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; + +/** + * @author Anindya Chatterjee. + */ +@Getter +public class WithFinalField { + private final long number; + @Setter + private String name; + + public WithFinalField() { + number = 2; + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithNitriteId.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithNitriteId.java new file mode 100644 index 000000000..b9b980f70 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithNitriteId.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee + */ +@Data +public class WithNitriteId { + @Id + public NitriteId idField; + public String name; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithNullId.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithNullId.java new file mode 100644 index 000000000..4a7059eaf --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithNullId.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithNullId { + @Id + private String name; + private long number; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithObjectId.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithObjectId.java new file mode 100644 index 000000000..ab1009b01 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithObjectId.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithObjectId { + @Id + private WithOutId withOutId; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithOutGetterSetter.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithOutGetterSetter.java new file mode 100644 index 000000000..eebfa6f6f --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithOutGetterSetter.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; + +/** + * @author Anindya Chatterjee. + */ +@EqualsAndHashCode +public class WithOutGetterSetter { + private String name; + private long number; + + public WithOutGetterSetter() { + name = "test"; + number = 2; + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithOutId.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithOutId.java new file mode 100644 index 000000000..43a6de490 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithOutId.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithOutId implements Comparable { + private String name; + private long number; + + @Override + public int compareTo(WithOutId o) { + return Long.compare(number, o.number); + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithPrivateConstructor.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithPrivateConstructor.java new file mode 100644 index 000000000..2570ebb50 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithPrivateConstructor.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; + +/** + * @author Anindya Chatterjee. + */ +@EqualsAndHashCode +public class WithPrivateConstructor { + private String name; + private long number; + + private WithPrivateConstructor() { + name = "test"; + number = 2; + } + + public static WithPrivateConstructor create(final String name, final long number) { + WithPrivateConstructor obj = new WithPrivateConstructor(); + obj.number = number; + obj.name = name; + return obj; + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithPublicField.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithPublicField.java new file mode 100644 index 000000000..d5fde086b --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithPublicField.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +public class WithPublicField { + @Id + public String name; + public long number; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithTransientField.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithTransientField.java new file mode 100644 index 000000000..2371e5998 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithTransientField.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithTransientField { + private transient String name; + @Id + private long number; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithoutEmbeddedId.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithoutEmbeddedId.java new file mode 100644 index 000000000..147513d86 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/repository/data/WithoutEmbeddedId.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee + */ +@Data +public class WithoutEmbeddedId { + @Id + private NestedId nestedId; + private String data; + + + @Data + public static class NestedId { + private Long id; + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/transaction/TransactionRepositoryTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/transaction/TransactionRepositoryTest.java new file mode 100644 index 000000000..50af4f042 --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/transaction/TransactionRepositoryTest.java @@ -0,0 +1,829 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.transaction; + +import com.github.javafaker.Faker; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.meta.Attributes; +import org.dizitart.no2.exceptions.NitriteIOException; +import org.dizitart.no2.exceptions.TransactionException; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.integration.repository.BaseObjectRepositoryTest; +import org.dizitart.no2.integration.repository.data.SubEmployee; +import org.dizitart.no2.transaction.Session; +import org.dizitart.no2.transaction.Transaction; +import org.junit.Test; + +import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class TransactionRepositoryTest extends BaseObjectRepositoryTest { + + @Test + public void testCommitInsert() { + ObjectRepository repository = db.getRepository(TxData.class); + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + TxData txData1 = new TxData(); + txData1.setId(1L); + txData1.setName("John"); + + txRepo.insert(txData1); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 1); + assertNotEquals(repository.find(where("name").eq("John")).size(), 1); + + transaction.commit(); + + assertEquals(repository.find(where("name").eq("John")).size(), 1); + } + } + } + + @Test + public void testRollbackInsert() { + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + TxData txData1 = new TxData(); + txData1.setId(1L); + txData1.setName("John"); + + TxData txData2 = new TxData(); + txData2.setId(2L); + txData2.setName("Jane"); + + txRepo.insert(txData1, txData2); + + txData2.setName("Molly"); + repository.insert(txData2); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 1); + assertEquals(repository.find(where("name").eq("John")).size(), 0); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(repository.find(where("name").eq("John")).size(), 0); + assertEquals(repository.find(where("name").eq("Molly")).size(), 1); + } + } + } + + @Test + public void testCommitUpdate() { + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(new TxData(1L, "John")); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + TxData txData1 = new TxData(1L, "Jane"); + txRepo.update(txData1, true); + + assertEquals(txRepo.find(where("name").eq("Jane")).size(), 1); + assertNotEquals(repository.find(where("name").eq("Jane")).size(), 1); + + transaction.commit(); + + assertEquals(repository.find(where("name").eq("Jane")).size(), 1); + } + } + } + + @Test + public void testRollbackUpdate() { + ObjectRepository repository = db.getRepository(TxData.class, "rollback"); + repository.createIndex("name"); + repository.insert(new TxData(1L, "Jane")); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + + ObjectRepository txRepo = transaction.getRepository(TxData.class, "rollback"); + + TxData txData1 = new TxData(); + txData1.setId(2L); + txData1.setName("John"); + + TxData txData2 = new TxData(); + txData2.setId(1L); + txData2.setName("Jane Doe"); + txRepo.update(txData2); + txRepo.insert(txData1); + + // just to create UniqueConstraintViolation for rollback + repository.insert(txData1); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 1); + assertEquals(txRepo.find(where("name").eq("Jane Doe")).size(), 1); + assertNotEquals(repository.find(where("name").eq("Jane Doe")).size(), 1); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(repository.find(where("name").eq("Jane")).size(), 1); + assertNotEquals(repository.find(where("name").eq("Jane Doe")).size(), 1); + } + } + } + + @Test + public void testCommitRemove() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + txRepo.remove(where("name").eq("John")); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 0); + assertEquals(repository.find(where("name").eq("John")).size(), 1); + + transaction.commit(); + + assertEquals(repository.find(where("name").eq("John")).size(), 0); + } + } + } + + @Test + public void testRollbackRemove() { + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + TxData txData1 = new TxData(1L, "John"); + repository.insert(txData1); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + txRepo.remove(where("name").eq("John")); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 0); + assertEquals(repository.find(where("name").eq("John")).size(), 1); + + TxData txData2 = new TxData(2L, "Jane"); + txRepo.insert(txData2); + repository.insert(txData2); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(repository.find(where("name").eq("John")).size(), 1); + assertEquals(repository.find(where("name").eq("Jane")).size(), 1); + } + } + } + + @Test + public void testCommitCreateIndex() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.createIndex(indexOptions(IndexType.FULL_TEXT), "name"); + + assertTrue(txRepo.hasIndex("name")); + assertFalse(repository.hasIndex("name")); + + transaction.commit(); + + assertTrue(repository.hasIndex("name")); + } + } + } + + @Test + public void testRollbackCreateIndex() { + TxData txData1 = new TxData(1L, "John"); + TxData txData2 = new TxData(2L, "Jane"); + + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(txData1); + + try(Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.createIndex(indexOptions(IndexType.FULL_TEXT), "name"); + + assertTrue(txRepo.hasIndex("name")); + assertFalse(repository.hasIndex("name")); + + txRepo.insert(txData2); + repository.insert(txData2); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertFalse(repository.hasIndex("name")); + } + } + } + + @Test + public void testCommitClear() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.clear(); + + assertEquals(0, txRepo.size()); + assertEquals(1, repository.size()); + + transaction.commit(); + + assertEquals(0, repository.size()); + } + } + } + + @Test + public void testRollbackClear() { + TxData txData1 = new TxData(1L, "John"); + TxData txData2 = new TxData(2L, "Jane"); + + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try(Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.clear(); + + assertEquals(0, txRepo.size()); + assertEquals(1, repository.size()); + + txRepo.insert(txData2); + repository.insert(txData2); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(2, repository.size()); + } + } + } + + @Test + public void testCommitDropIndex() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.dropIndex("name"); + + assertFalse(txRepo.hasIndex("name")); + assertTrue(repository.hasIndex("name")); + + transaction.commit(); + + assertFalse(repository.hasIndex("name")); + } + } + } + + @Test + public void testRollbackDropIndex() { + TxData txData1 = new TxData(1L, "John"); + TxData txData2 = new TxData(2L, "Jane"); + + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try(Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.dropIndex("name"); + + assertFalse(txRepo.hasIndex("name")); + assertTrue(repository.hasIndex("name")); + + txRepo.insert(txData2); + repository.insert(txData2); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertTrue(repository.hasIndex("name")); + } + } + } + + @Test + public void testCommitDropAllIndices() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.dropAllIndices(); + + assertFalse(txRepo.hasIndex("name")); + assertTrue(repository.hasIndex("name")); + + transaction.commit(); + + assertFalse(repository.hasIndex("name")); + } + } + } + + @Test + public void testRollbackDropAllIndices() { + TxData txData1 = new TxData(1L, "John"); + TxData txData2 = new TxData(2L, "Jane"); + + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try(Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.dropAllIndices(); + + assertFalse(txRepo.hasIndex("name")); + assertTrue(repository.hasIndex("name")); + + txRepo.insert(txData2); + repository.insert(txData2); + + throw new TransactionException("failed"); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertTrue(repository.hasIndex("name")); + } + } + } + + @Test + public void testCommitDropRepository() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.drop(); + + boolean expectedException = false; + try { + assertEquals(0, txRepo.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + assertEquals(1, repository.size()); + + transaction.commit(); + + expectedException = false; + try { + assertEquals(0, repository.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + } + } + } + + @Test + public void testRollbackDropRepository() { + TxData txData1 = new TxData(1L, "John"); + + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try(Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.drop(); + + boolean expectedException = false; + try { + assertEquals(0, txRepo.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + assertEquals(1, repository.size()); + + throw new TransactionException("failed"); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(1, repository.size()); + } + } + } + + @Test + public void testCommitSetAttribute() { + ObjectRepository repository = db.getRepository(TxData.class); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + Attributes attributes = new Attributes(); + Map hashMap = new HashMap<>(); + hashMap.put("key", "value"); + attributes.setAttributes(hashMap); + txRepo.setAttributes(attributes); + + assertNull(repository.getAttributes()); + + transaction.commit(); + + assertEquals("value", repository.getAttributes().get("key")); + } + } + } + + @Test + public void testRollbackSetAttribute() { + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + Attributes attributes = new Attributes(); + Map map = new HashMap<>(); + map.put("key", "value"); + attributes.setAttributes(map); + txRepo.setAttributes(attributes); + + txRepo.insert(new TxData(1L, "John")); + txRepo.insert(new TxData(2L, "Jane")); + + assertNull(repository.getAttributes()); + + // just to create UniqueConstraintViolation for rollback + repository.insert(new TxData(2L, "Jane")); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 1); + assertNotEquals(repository.find(where("name").eq("John")).size(), 1); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertNull(repository.getAttributes().get("key")); + } + } + } + + @Test + public void testConcurrentInsertAndRemove() { + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex(indexOptions(IndexType.NON_UNIQUE), "name"); + Faker faker = new Faker(); + List> futures = new ArrayList<>(); + + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + final long fi = i; + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + for (long j = 0; j < 10; j++) { + TxData txData = new TxData(j + (fi * 10), faker.name().name()); + txRepo.insert(txData); + } + + txRepo.remove(where("id").eq(2L + (fi * 10))); + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(90, repository.size()); + } + } + + @Test + public void testConcurrentInsert() { + ObjectRepository repository = db.getRepository(TxData.class); + Faker faker = new Faker(); + List> futures = new ArrayList<>(); + + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + final long fi = i; + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + for (long j = 0; j < 10; j++) { + TxData txData = new TxData(j + (fi * 10), faker.name().name()); + txRepo.insert(txData); + } + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(100, repository.size()); + } + } + + @Test + public void testConcurrentUpdate() { + ObjectRepository repository = db.getRepository(TxData.class); + Faker faker = new Faker(); + for (long j = 0; j < 10; j++) { + TxData txData = new TxData(j, faker.name().name()); + repository.insert(txData); + } + + List> futures = new ArrayList<>(); + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + for (int j = 0; j < 10; j++) { + TxData txData = new TxData((long) j, faker.name().name()); + txRepo.update(where("id").eq(j), txData); + } + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(10, repository.size()); + } + } + + @Test + public void testTransactionOnDifferentRepositoriesAndCollections() { + ObjectRepository repo1 = db.getRepository(TxData.class); + ObjectRepository repo2 = db.getRepository(TxData.class, "2"); + ObjectRepository repo3 = db.getRepository(SubEmployee.class); + NitriteCollection col1 = db.getCollection("test1"); + col1.createIndex("id"); + + Faker faker = new Faker(); + + try(Session session = db.createSession()) { + Transaction transaction = session.beginTransaction(); + + ObjectRepository txRepo1 = transaction.getRepository(TxData.class); + ObjectRepository txRepo2 = transaction.getRepository(TxData.class, "2"); + ObjectRepository txRepo3 = transaction.getRepository(SubEmployee.class); + NitriteCollection test1 = transaction.getCollection("test1"); + + for (long i = 0; i < 10; i++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", i); + test1.insert(document); + + TxData txData1 = new TxData(i, faker.name().name()); + txRepo1.insert(txData1); + + TxData txData2 = new TxData(i + 10, faker.name().name()); + txRepo2.insert(txData2); + + SubEmployee employee = new SubEmployee(); + employee.setAddress(faker.address().fullAddress()); + employee.setEmpId(i); + employee.setJoinDate(faker.date().birthday()); + txRepo3.insert(employee); + } + + assertEquals(test1.size(), 10); + assertEquals(txRepo1.size(), 10); + assertEquals(txRepo2.size(), 10); + assertEquals(txRepo3.size(), 10); + + assertEquals(col1.size(), 0); + assertEquals(repo1.size(), 0); + assertEquals(repo2.size(), 0); + assertEquals(repo3.size(), 0); + + transaction.commit(); + + assertEquals(col1.size(), 10); + assertEquals(repo1.size(), 10); + assertEquals(repo2.size(), 10); + assertEquals(repo3.size(), 10); + } + + Transaction transaction = null; + try (Session session = db.createSession()) { + transaction = session.beginTransaction(); + + ObjectRepository txRepo1 = transaction.getRepository(TxData.class); + ObjectRepository txRepo2 = transaction.getRepository(TxData.class, "2"); + ObjectRepository txRepo3 = transaction.getRepository(SubEmployee.class); + NitriteCollection test1 = transaction.getCollection("test1"); + + for (long i = 0; i < 10; i++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", i + 10); + test1.insert(document); + + TxData txData1 = new TxData(i + 10, faker.name().name()); + txRepo1.insert(txData1); + + TxData txData2 = new TxData(i + 20, faker.name().name()); + txRepo2.insert(txData2); + + SubEmployee employee = new SubEmployee(); + employee.setAddress(faker.address().fullAddress()); + employee.setEmpId(i + 10); + employee.setJoinDate(faker.date().birthday()); + txRepo3.insert(employee); + } + + assertEquals(test1.size(), 20); + assertEquals(txRepo1.size(), 20); + assertEquals(txRepo2.size(), 20); + assertEquals(txRepo3.size(), 20); + + assertEquals(col1.size(), 10); + assertEquals(repo1.size(), 10); + assertEquals(repo2.size(), 10); + assertEquals(repo3.size(), 10); + + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", 12L); + col1.insert(document); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + + assertEquals(col1.size(), 11); // last doc added + assertEquals(repo1.size(), 10); + assertEquals(repo2.size(), 10); + assertEquals(repo3.size(), 10); + } + } + + @Test(expected = TransactionException.class) + public void testFailureOnClosedTransaction() { + try(Session session = db.createSession()) { + Transaction transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.insert(new TxData(1L, "John")); + transaction.commit(); + + txRepo.insert(new TxData(2L, "Jane")); + fail(); + } + } +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/transaction/TxData.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/transaction/TxData.java new file mode 100644 index 000000000..57461811e --- /dev/null +++ b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/integration/transaction/TxData.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.transaction; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +class TxData { + @Id + private Long id; + private String name; +} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/BaseObjectRepositoryTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/BaseObjectRepositoryTest.java deleted file mode 100644 index 6dbd8a040..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/BaseObjectRepositoryTest.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.mapper.JacksonMapperModule; -import org.dizitart.no2.mvstore.MVStoreModule; -import org.dizitart.no2.mvstore.MVStoreModuleBuilder; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.test.data.*; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Collection; -import java.util.UUID; - -import static org.dizitart.no2.filters.Filter.ALL; -import static org.junit.Assert.assertTrue; - -@RunWith(value = Parameterized.class) -public abstract class BaseObjectRepositoryTest { - @Parameterized.Parameter - public boolean inMemory = false; - @Parameterized.Parameter(value = 1) - public boolean isProtected = false; - @Parameterized.Parameter(value = 2) - public boolean isCompressed = false; - @Parameterized.Parameter(value = 3) - public boolean isAutoCommit = false; - @Parameterized.Parameter(value = 4) - public boolean isAutoCompact = false; - protected Nitrite db; - ObjectRepository companyRepository; - ObjectRepository employeeRepository; - ObjectRepository aObjectRepository; - ObjectRepository cObjectRepository; - private final String fileName = getRandomTempDbFile(); - - @Rule - public Retry retry = new Retry(3); - - @Parameterized.Parameters(name = "InMemory = {0}, Protected = {1}, " + - "Compressed = {2}, AutoCommit = {3}") - public static Collection data() { - return Arrays.asList(new Object[][]{ - {false, false, false, false, false}, - {false, false, false, true, false}, - {false, false, true, false, false}, - {false, false, true, true, false}, - {false, true, false, false, false}, - {false, true, false, true, false}, - {false, true, true, false, false}, - {false, true, true, true, true}, - {true, false, false, false, true}, - {true, false, false, true, true}, - {true, false, true, false, true}, - {true, false, true, true, true}, - {true, true, false, false, true}, - {true, true, false, true, true}, - {true, true, true, false, true}, - {true, true, true, true, true}, - }); - } - - public static String getRandomTempDbFile() { - String dataDir = System.getProperty("java.io.tmpdir") + File.separator + "nitrite" + File.separator + "data"; - File file = new File(dataDir); - if (!file.exists()) { - assertTrue(file.mkdirs()); - } - return file.getPath() + File.separator + UUID.randomUUID().toString() + ".db"; - } - - @Before - public void setUp() { - openDb(); - - companyRepository = db.getRepository(Company.class); - employeeRepository = db.getRepository(Employee.class); - - aObjectRepository = db.getRepository(ClassA.class); - cObjectRepository = db.getRepository(ClassC.class); - - for (int i = 0; i < 10; i++) { - Company company = DataGenerator.generateCompanyRecord(); - companyRepository.insert(company); - Employee employee = DataGenerator.generateEmployee(); - employee.setEmpId((long) i + 1); - employeeRepository.insert(employee); - - aObjectRepository.insert(ClassA.create(i + 50)); - cObjectRepository.insert(ClassC.create(i + 30)); - } - } - - private void openDb() { - MVStoreModuleBuilder builder = MVStoreModule.withConfig(); - - if (isCompressed) { - builder.compress(true); - } - - if (!isAutoCommit) { - builder.autoCommit(false); - } - - if (!inMemory) { - builder.filePath(fileName); - } - - MVStoreModule storeModule = builder.build(); - NitriteBuilder nitriteBuilder = Nitrite.builder() - .loadModule(new JacksonMapperModule()) - .fieldSeparator(".") - .loadModule(storeModule); - - if (isProtected) { - db = nitriteBuilder.openOrCreate("test-user", "test-password"); - } else { - db = nitriteBuilder.openOrCreate(); - } - } - - @After - public void clear() throws IOException { - if (companyRepository != null && !companyRepository.isDropped()) { - companyRepository.remove(ALL); - } - - if (employeeRepository != null && !employeeRepository.isDropped()) { - employeeRepository.remove(ALL); - } - - if (aObjectRepository != null && !aObjectRepository.isDropped()) { - aObjectRepository.remove(ALL); - } - - if (cObjectRepository != null && !cObjectRepository.isDropped()) { - cObjectRepository.remove(ALL); - } - - if (db != null && !db.isClosed()) { - db.commit(); - db.close(); - } - - if (!inMemory) { - Files.delete(Paths.get(fileName)); - } - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/InternalClass.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/InternalClass.java deleted file mode 100644 index 8b6127a61..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/InternalClass.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test; - -import lombok.Data; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Data -class InternalClass { - @Id - private long id; - private String name; -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/NitriteIdAsIdTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/NitriteIdAsIdTest.java deleted file mode 100644 index 00c678320..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/NitriteIdAsIdTest.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test; - -import lombok.Data; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.common.util.Iterables; -import org.dizitart.no2.exceptions.InvalidIdException; -import org.dizitart.no2.mapper.JacksonMapper; -import org.dizitart.no2.repository.Cursor; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Id; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; - -import static org.dizitart.no2.module.NitriteModule.module; -import static org.dizitart.no2.test.BaseObjectRepositoryTest.getRandomTempDbFile; -import static org.dizitart.no2.test.TestUtil.createDb; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee - */ -public class NitriteIdAsIdTest { - private final String fileName = getRandomTempDbFile(); - private Nitrite db; - private ObjectRepository repo; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void before() { - JacksonMapper mapper = new JacksonMapper(); - db = createDb(fileName, module(mapper)); - repo = db.getRepository(WithNitriteId.class); - } - - @After - public void after() throws IOException { - db.close(); - Files.delete(Paths.get(fileName)); - } - - @Test - public void testNitriteIdField() { - WithNitriteId item1 = new WithNitriteId(); - item1.name = "first"; - - WithNitriteId item2 = new WithNitriteId(); - item2.name = "second"; - - repo.insert(item1, item2); - - Cursor cursor = repo.find(); - for (WithNitriteId withNitriteId : cursor) { - System.out.println(withNitriteId.name); - assertNotNull(withNitriteId.idField); - } - - WithNitriteId withNitriteId = cursor.firstOrNull(); - withNitriteId.name = "third"; - - NitriteId id = withNitriteId.idField; - repo.update(withNitriteId); - - WithNitriteId byId = repo.getById(id); - assertEquals(withNitriteId, byId); - assertEquals(repo.size(), 2); - } - - @Test(expected = InvalidIdException.class) - public void setIdDuringInsert() { - WithNitriteId item1 = new WithNitriteId(); - item1.name = "first"; - item1.idField = NitriteId.newId(); - - repo.insert(item1); - } - - @Test - public void changeIdDuringUpdate() { - WithNitriteId item2 = new WithNitriteId(); - item2.name = "second"; - WriteResult result = repo.insert(item2); - NitriteId nitriteId = Iterables.firstOrNull(result); - WithNitriteId byId = repo.getById(nitriteId); - byId.idField = NitriteId.newId(); - - result = repo.update(byId); - assertEquals(result.getAffectedCount(), 0); - assertEquals(repo.size(), 1); - } - - @Data - private static class WithNitriteId { - @Id - private NitriteId idField; - private String name; - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/ObjectCursorTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/ObjectCursorTest.java deleted file mode 100644 index 971a5ff7e..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/ObjectCursorTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test; - -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.repository.Cursor; -import org.dizitart.no2.test.data.Employee; -import org.junit.Test; - -import java.util.AbstractCollection; -import java.util.Date; - -/** - * @author Anindya Chatterjee - */ -public class ObjectCursorTest extends BaseObjectRepositoryTest { - - @Test(expected = ValidationException.class) - public void testProjectForInterface() { - Cursor cursor = employeeRepository.find(); - cursor.project(Comparable.class); - } - - @Test(expected = ValidationException.class) - public void testProjectForPrimitive() { - Cursor cursor = employeeRepository.find(); - cursor.project(int.class); - } - - @Test(expected = ValidationException.class) - public void testProjectForArray() { - Cursor cursor = employeeRepository.find(); - cursor.project(String[].class); - } - - @Test(expected = ValidationException.class) - public void testProjectForAbstractClass() { - Cursor cursor = employeeRepository.find(); - cursor.project(AbstractCollection.class); - } - - @Test(expected = ValidationException.class) - public void testProjectForValueType() { - Cursor cursor = employeeRepository.find(); - RecordStream project = cursor.project(Date.class); - project.forEach(System.out::println); - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/ObjectRepositoryNegativeTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/ObjectRepositoryNegativeTest.java deleted file mode 100644 index 975d3ac77..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/ObjectRepositoryNegativeTest.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.*; -import org.dizitart.no2.mapper.JacksonMapperModule; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.test.data.*; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.locationtech.jts.geom.LineString; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -/** - * @author Anindya Chatterjee. - */ -public class ObjectRepositoryNegativeTest { - private final String dbPath = BaseObjectRepositoryTest.getRandomTempDbFile(); - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - db = TestUtil.createDb(dbPath, new JacksonMapperModule()); - } - - @After - public void close() throws IOException { - db.close(); - db = null; - Files.delete(Paths.get(dbPath)); - } - - @Test(expected = ObjectMappingException.class) - public void testWithCircularReference() { - ObjectRepository repository = db.getRepository(WithCircularReference.class); - - WithCircularReference parent = new WithCircularReference(); - parent.setName("parent"); - WithCircularReference object = new WithCircularReference(); - object.setName("test"); - object.setParent(parent); - // circular reference - parent.setParent(object); - - repository.insert(object); - WithCircularReference instance = repository.getById("parent"); - assertEquals(instance.getName(), object.getName()); - assertEquals(instance.getParent().getName(), object.getParent().getName()); - } - - @Test(expected = ObjectMappingException.class) - public void testWithCustomConstructor() { - ObjectRepository repository = db.getRepository(WithCustomConstructor.class); - - WithCustomConstructor object = new WithCustomConstructor("test", 2L); - - repository.insert(object); - WithCustomConstructor instance = repository.getById("test"); - assertEquals(object.getName(), instance.getName()); - assertEquals(object.getNumber(), instance.getNumber()); - } - - @Test(expected = InvalidIdException.class) - public void testWithEmptyStringId() { - ObjectRepository repository = db.getRepository(WithEmptyStringId.class); - WithEmptyStringId object = new WithEmptyStringId(); - object.setName(""); // empty id value - - WriteResult result = repository.insert(object); - for (NitriteId id : result) { - WithEmptyStringId instance = repository.getById(id); - assertEquals(instance, object); - } - } - - @Test(expected = InvalidIdException.class) - public void testWithNullId() { - ObjectRepository repository = db.getRepository(WithNullId.class); - WithNullId object = new WithNullId(); - - WriteResult result = repository.insert(object); - for (NitriteId id : result) { - WithNullId instance = repository.getById(id); - assertEquals(instance, object); - } - } - - @Test(expected = InvalidOperationException.class) - public void testFindResultRemove() { - ObjectRepository repository = db.getRepository(Employee.class); - repository.insert(DataGenerator.generateEmployee()); - RecordStream result = repository.find(); - result.iterator().remove(); - } - - @Test(expected = InvalidOperationException.class) - public void testWithObjectId() { - ObjectRepository repository = db.getRepository(WithObjectId.class); - WithOutId id = new WithOutId(); - id.setName("test"); - id.setNumber(1); - - WithObjectId object = new WithObjectId(); - object.setWithOutId(id); - repository.insert(object); - } - - @Test(expected = NotIdentifiableException.class) - public void testUpdateNoId() { - ObjectRepository repository = db.getRepository(WithOutId.class); - WithOutId object = new WithOutId(); - object.setName("name"); - object.setNumber(1L); - repository.update(object); - } - - @Test(expected = NotIdentifiableException.class) - public void testRemoveNoId() { - ObjectRepository repository = db.getRepository(WithOutId.class); - WithOutId object = new WithOutId(); - object.setName("name"); - object.setNumber(1L); - repository.remove(object); - } - - @Test(expected = ObjectMappingException.class) - public void testProjectionFailedInstantiate() { - ObjectRepository repository = db.getRepository(WithOutId.class); - WithOutId object = new WithOutId(); - object.setName("name"); - object.setNumber(1L); - repository.insert(object); - - RecordStream project = repository.find().project(LineString.class); - assertNull(project); - } - - @Test(expected = ValidationException.class) - public void testNullInsert() { - ObjectRepository repository = db.getRepository(WithOutId.class); - repository.insert(null); - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/ObjectRepositoryTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/ObjectRepositoryTest.java deleted file mode 100644 index 7e3203fed..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/ObjectRepositoryTest.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.mapper.JacksonMapperModule; -import org.dizitart.no2.repository.Cursor; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.test.data.*; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Date; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.awaitility.Awaitility.await; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class ObjectRepositoryTest { - private final String dbPath = BaseObjectRepositoryTest.getRandomTempDbFile(); - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - db = TestUtil.createDb(dbPath, new JacksonMapperModule()); - } - - @After - public void close() throws IOException { - db.close(); - db = null; - Files.delete(Paths.get(dbPath)); - } - - @Test - public void testWithClassField() { - ObjectRepository repository = db.getRepository(WithClassField.class); - - WithClassField object = new WithClassField(); - object.setName("test"); - object.setClazz(String.class); - - repository.insert(object); - WithClassField instance = repository.getById("test"); - assertEquals(instance.getName(), object.getName()); - assertEquals(instance.getClazz(), object.getClazz()); - } - - @Test - public void testWithFinalField() { - ObjectRepository repository = db.getRepository(WithFinalField.class); - WithFinalField object = new WithFinalField(); - object.setName("test"); - - repository.insert(object); - for (WithFinalField instance : repository.find()) { - assertEquals(object.getName(), instance.getName()); - assertEquals(object.getNumber(), instance.getNumber()); - } - } - - @Test - public void testWithOutGetterSetter() { - ObjectRepository repository = db.getRepository(WithOutGetterSetter.class); - WithOutGetterSetter object = new WithOutGetterSetter(); - - repository.insert(object); - for (WithOutGetterSetter instance : repository.find()) { - assertEquals(object, instance); - } - } - - @Test - public void testWithOutId() { - ObjectRepository repository = db.getRepository(WithOutId.class); - WithOutId object = new WithOutId(); - object.setName("test"); - object.setNumber(2); - - repository.insert(object); - for (WithOutId instance : repository.find()) { - assertEquals(object.getName(), instance.getName()); - assertEquals(object.getNumber(), instance.getNumber()); - } - } - - @Test - public void testWithPublicField() { - ObjectRepository repository = db.getRepository(WithPublicField.class); - WithPublicField object = new WithPublicField(); - object.name = "test"; - object.number = 2; - - repository.insert(object); - WithPublicField instance = repository.getById("test"); - assertEquals(object.name, instance.name); - assertEquals(object.number, instance.number); - } - - @Test - public void testWithTransientField() { - ObjectRepository repository = db.getRepository(WithTransientField.class); - WithTransientField object = new WithTransientField(); - object.setNumber(2); - object.setName("test"); - - repository.insert(object); - WithTransientField instance = repository.getById(2L); - assertNotEquals(object.getName(), instance.getName()); - assertNull(instance.getName()); - assertEquals(object.getNumber(), instance.getNumber()); - } - - @Test - public void testWriteThousandRecords() { - int count = 5000; - - ObjectRepository repository = db.getRepository(StressRecord.class); - - for (int i = 0; i < count; i++) { - StressRecord record = new StressRecord(); - record.setFirstName(UUID.randomUUID().toString()); - record.setFailed(false); - record.setLastName(UUID.randomUUID().toString()); - record.setProcessed(false); - - repository.insert(record); - } - - Cursor cursor - = repository.find(where("failed").eq(false)); - for (StressRecord record : cursor) { - record.setProcessed(true); - repository.update(where("firstName").eq(record.getFirstName()), record); - } - } - - @Test - public void testWithPackagePrivateClass() { - ObjectRepository repository = db.getRepository(InternalClass.class); - InternalClass internalClass = new InternalClass(); - internalClass.setId(1); - internalClass.setName("name"); - - repository.insert(internalClass); - InternalClass instance = repository.getById((long) 1); - assertEquals(internalClass.getName(), instance.getName()); - assertEquals(internalClass.getId(), instance.getId()); - } - - @Test - public void testWithPrivateConstructor() { - ObjectRepository repository = - db.getRepository(WithPrivateConstructor.class); - - WithPrivateConstructor object = WithPrivateConstructor.create("test", 2L); - repository.insert(object); - for (WithPrivateConstructor instance : repository.find()) { - assertEquals(object, instance); - } - } - - @Test - public void testWithDateAsId() { - ObjectRepository repository = db.getRepository(WithDateId.class); - - WithDateId object1 = new WithDateId(); - object1.setId(new Date(1482773634L)); - object1.setName("first date"); - repository.insert(object1); - - WithDateId object2 = new WithDateId(); - object2.setName("second date"); - object2.setId(new Date(1482773720L)); - repository.insert(object2); - - assertEquals(repository.find(where("id").eq(new Date(1482773634L))) - .firstOrNull(), object1); - assertEquals(repository.find(where("id").eq(new Date(1482773720L))) - .firstOrNull(), object2); - } - - @Test - public void testWithIdInheritance() { - ObjectRepository repository = db.getRepository(ChildClass.class); - assertTrue(repository.hasIndex("id")); - assertTrue(repository.hasIndex("date")); - assertTrue(repository.hasIndex("text")); - - ChildClass childClass = new ChildClass(); - childClass.setName("first"); - childClass.setDate(new Date(100000L)); - childClass.setId(1L); - childClass.setText("I am first class"); - repository.insert(childClass); - - childClass = new ChildClass(); - childClass.setName("seconds"); - childClass.setDate(new Date(100001L)); - childClass.setId(2L); - childClass.setText("I am second class"); - repository.insert(childClass); - - childClass = new ChildClass(); - childClass.setName("third"); - childClass.setDate(new Date(100002L)); - childClass.setId(3L); - childClass.setText("I am third class"); - repository.insert(childClass); - - assertEquals(repository.find(where("text").text("class")).size(), 3); - assertEquals(repository.find(where("text").text("second")).size(), 0); // filtered in stop words - assertEquals(repository.find(where("date").eq(new Date(100000L))).size(), 1); - assertEquals(repository.find(where("id").eq(1L)).size(), 1); - } - - @Test - public void testAttributes() { - ObjectRepository repository = db.getRepository(WithDateId.class); - Attributes attributes = new Attributes(repository.getDocumentCollection().getName()); - repository.setAttributes(attributes); - assertEquals(repository.getAttributes(), attributes); - } - - @Test - public void testIssue217() { - ObjectRepository employeeRepo = db.getRepository(Employee.class); - AtomicInteger counter = new AtomicInteger(0); - employeeRepo.subscribe(eventInfo -> counter.incrementAndGet()); - - ObjectRepository employeeRepo2 = db.getRepository(Employee.class); - employeeRepo2.insert(DataGenerator.generateEmployee()); - await().atMost(5, TimeUnit.SECONDS).until(() -> counter.get() == 1); - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/ProjectionTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/ProjectionTest.java deleted file mode 100644 index eddba3950..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/ProjectionTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test; - -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.test.data.SubEmployee; -import org.junit.Test; - -import java.util.Iterator; - -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -public class ProjectionTest extends BaseObjectRepositoryTest { - - @Test - public void testHasMore() { - RecordStream iterable = employeeRepository.find().skipLimit(0, 5) - .project(SubEmployee.class); - assertFalse(iterable.isEmpty()); - } - - @Test - public void testSize() { - RecordStream iterable = employeeRepository.find().skipLimit(0, 5) - .project(SubEmployee.class); - assertEquals(iterable.size(), 5); - } - - @Test - public void testToString() { - RecordStream iterable = employeeRepository.find().skipLimit(0, 5) - .project(SubEmployee.class); - assertNotNull(iterable.toString()); - } - - @Test(expected = InvalidOperationException.class) - public void testRemove() { - RecordStream iterable = employeeRepository.find().skipLimit(0, 5) - .project(SubEmployee.class); - Iterator iterator = iterable.iterator(); - if (iterator.hasNext()) { - iterator.next(); - iterator.remove(); - } - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/RepositoryJoinTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/RepositoryJoinTest.java deleted file mode 100644 index a11f13c4c..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/RepositoryJoinTest.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test; - -import lombok.Data; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.Lookup; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.mapper.JacksonMapperModule; -import org.dizitart.no2.mvstore.MVStoreModule; -import org.dizitart.no2.mvstore.MVStoreModuleBuilder; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Id; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; - -import static org.dizitart.no2.filters.Filter.ALL; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -@RunWith(value = Parameterized.class) -public class RepositoryJoinTest { - @Parameterized.Parameter - public boolean inMemory = false; - @Parameterized.Parameter(value = 1) - public boolean isProtected = false; - @Parameterized.Parameter(value = 2) - public boolean isCompressed = false; - @Parameterized.Parameter(value = 3) - public boolean isAutoCommit = false; - @Parameterized.Parameter(value = 4) - public boolean isAutoCompact = false; - protected Nitrite db; - private final String fileName = BaseObjectRepositoryTest.getRandomTempDbFile(); - private ObjectRepository personRepository; - private ObjectRepository
addressRepository; - - @Rule - public Retry retry = new Retry(3); - - @Parameterized.Parameters(name = "InMemory = {0}, Protected = {1}, " + - "Compressed = {2}, AutoCommit = {3}, AutoCompact = {4}") - public static Collection data() { - return Arrays.asList(new Object[][]{ - {false, false, false, false, false}, - {false, false, false, true, false}, - {false, false, true, false, false}, - {false, false, true, true, false}, - {false, true, false, false, false}, - {false, true, false, true, false}, - {false, true, true, false, false}, - {false, true, true, true, true}, - {true, false, false, false, true}, - {true, false, false, true, true}, - {true, false, true, false, true}, - {true, false, true, true, true}, - {true, true, false, false, true}, - {true, true, false, true, true}, - {true, true, true, false, true}, - {true, true, true, true, true}, - }); - } - - @Before - public void setUp() { - openDb(); - - personRepository = db.getRepository(Person.class); - addressRepository = db.getRepository(Address.class); - - for (int i = 0; i < 10; i++) { - Person person = new Person(); - person.setId(Integer.toString(i)); - person.setName("Person " + i); - personRepository.insert(person); - - Address address = new Address(); - address.setPersonId(Integer.toString(i)); - address.setStreet("Street address " + i); - addressRepository.insert(address); - - if (i == 5) { - Address address2 = new Address(); - address2.setPersonId(Integer.toString(i)); - address2.setStreet("Street address 2nd " + i); - addressRepository.insert(address2); - } - } - } - - private void openDb() { - MVStoreModuleBuilder builder = MVStoreModule.withConfig(); - - if (isCompressed) { - builder.compress(true); - } - - if (!isAutoCommit) { - builder.autoCommit(false); - } - - if (!inMemory) { - builder.filePath(fileName); - } - - MVStoreModule storeModule = builder.build(); - NitriteBuilder nitriteBuilder = Nitrite.builder() - .fieldSeparator(".") - .loadModule(storeModule); - - nitriteBuilder.loadModule(new JacksonMapperModule()); - - if (isProtected) { - db = nitriteBuilder.openOrCreate("test-user1", "test-password1"); - } else { - db = nitriteBuilder.openOrCreate(); - } - } - - @After - public void clear() throws IOException { - if (personRepository != null && !personRepository.isDropped()) { - personRepository.remove(ALL); - } - - if (addressRepository != null && !addressRepository.isDropped()) { - addressRepository.remove(ALL); - } - - if (db != null) { - db.commit(); - db.close(); - } - - if (!inMemory) { - Files.delete(Paths.get(fileName)); - } - } - - @Test - public void testJoin() { - Lookup lookup = new Lookup(); - lookup.setLocalField("id"); - lookup.setForeignField("personId"); - lookup.setTargetField("addresses"); - - RecordStream result - = personRepository.find().join(addressRepository.find(), lookup, - PersonDetails.class); - assertEquals(result.size(), 10); - - for (PersonDetails personDetails : result) { - Address[] addresses = personDetails.addresses.toArray(new Address[0]); - if (personDetails.id.equals("5")) { - assertEquals(addresses.length, 2); - } else { - assertEquals(addresses.length, 1); - assertEquals(addresses[0].personId, personDetails.getId()); - } - } - - result = personRepository.find().skipLimit(0, 5).join(addressRepository.find(), lookup, - PersonDetails.class); - - assertEquals(result.size(), 5); - assertFalse(result.isEmpty()); - assertNotNull(result.toString()); - } - - @Test(expected = InvalidOperationException.class) - public void testRemove() { - Lookup lookup = new Lookup(); - lookup.setLocalField("id"); - lookup.setForeignField("personId"); - lookup.setTargetField("addresses"); - - RecordStream result - = personRepository.find().join(addressRepository.find(), lookup, - PersonDetails.class); - assertEquals(result.size(), 10); - - Iterator iterator = result.iterator(); - if (iterator.hasNext()) { - iterator.next(); - iterator.remove(); - } - } - - @Data - public static class Person { - @Id - private NitriteId nitriteId; - private String id; - private String name; - } - - @Data - public static class Address { - @Id - private NitriteId nitriteId; - private String personId; - private String street; - } - - @Data - public static class PersonDetails { - @Id - private NitriteId nitriteId; - private String id; - private String name; - private List
addresses; - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/RepositoryModificationTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/RepositoryModificationTest.java deleted file mode 100644 index d9f8b9668..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/RepositoryModificationTest.java +++ /dev/null @@ -1,515 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.InvalidIdException; -import org.dizitart.no2.exceptions.UniqueConstraintException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexEntry; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.repository.Cursor; -import org.dizitart.no2.test.data.Company; -import org.dizitart.no2.test.data.DataGenerator; -import org.dizitart.no2.test.data.Employee; -import org.dizitart.no2.test.data.Note; -import org.junit.Test; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Collection; -import java.util.Date; -import java.util.Locale; - -import static org.awaitility.Awaitility.await; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class RepositoryModificationTest extends BaseObjectRepositoryTest { - @Test - public void testCreateIndex() { - assertTrue(companyRepository.hasIndex("companyName")); - assertFalse(companyRepository.hasIndex("dateCreated")); - - companyRepository.createIndex("dateCreated", IndexOptions.indexOptions(IndexType.NonUnique)); - assertTrue(companyRepository.hasIndex("dateCreated")); - assertFalse(companyRepository.isIndexing("dateCreated")); - } - - @Test - public void testRebuildIndex() { - companyRepository.createIndex("dateCreated", IndexOptions.indexOptions(IndexType.NonUnique)); - assertFalse(companyRepository.isIndexing("dateCreated")); - - companyRepository.rebuildIndex("dateCreated", true); - assertTrue(companyRepository.isIndexing("dateCreated")); - - await().until(() -> !companyRepository.isIndexing("dateCreated")); - } - - @Test - public void testListIndexes() { - Collection indices = companyRepository.listIndices(); - assertEquals(indices.size(), 2); - - companyRepository.createIndex("dateCreated", IndexOptions.indexOptions(IndexType.NonUnique)); - indices = companyRepository.listIndices(); - assertEquals(indices.size(), 3); - } - - @Test - public void testDropIndex() { - testListIndexes(); - companyRepository.dropIndex("dateCreated"); - Collection indices = companyRepository.listIndices(); - assertEquals(indices.size(), 2); - } - - @Test - public void testDropAllIndex() { - testListIndexes(); - companyRepository.dropAllIndices(); - Collection indices = companyRepository.listIndices(); - assertEquals(indices.size(), 0); - } - - @Test - public void testCompanyRecord() { - Cursor cursor = companyRepository.find(); - assertEquals(cursor.size(), 10); - assertFalse(cursor.isEmpty()); - } - - @Test - public void testInsert() { - Company company = DataGenerator.generateCompanyRecord(); - Cursor cursor = companyRepository.find(); - assertEquals(cursor.size(), 10); - - companyRepository.insert(company); - cursor = companyRepository.find(); - assertEquals(cursor.size(), 11); - - Company company1 = DataGenerator.generateCompanyRecord(); - Company company2 = DataGenerator.generateCompanyRecord(); - companyRepository.insert(new Company[]{company1, company2}); - cursor = companyRepository.find(); - assertEquals(cursor.size(), 13); - } - - @Test - public void testUpdateWithFilter() { - employeeRepository.remove(Filter.ALL); - - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("abcd road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(new Date()); - Note empNote = new Note(); - empNote.setNoteId(23L); - empNote.setText("sample text note"); - employee.setEmployeeNote(empNote); - - employeeRepository.insert(employee); - Cursor result = employeeRepository.find(); - assertEquals(result.size(), 1); - for (Employee e : result) { - assertEquals(e.getAddress(), "abcd road"); - } - - Employee updated = new Employee(employee); - updated.setAddress("xyz road"); - WriteResult writeResult = employeeRepository.update(where("empId").eq(12L), updated); - assertEquals(writeResult.getAffectedCount(), 1); - result = employeeRepository.find(); - assertEquals(result.size(), 1); - for (Employee e : result) { - assertEquals(e.getAddress(), "xyz road"); - } - } - - @Test - public void testUpdateWithJustOnceFalse() throws ParseException { - Date joiningDate = new Date(); - prepareUpdateWithOptions(joiningDate); - - SimpleDateFormat simpleDateFormat - = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); - Date newJoiningDate = simpleDateFormat.parse("2012-07-01T16:02:48.440Z"); - - Document updated1 = createDocument(); - updated1.put("joinDate", newJoiningDate); - - WriteResult writeResult - = employeeRepository.update(where("empId").eq(12L), updated1, false); - assertEquals(writeResult.getAffectedCount(), 1); - - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 1); - result = employeeRepository.find(where("joinDate").eq(newJoiningDate)); - assertEquals(result.size(), 1); - - employeeRepository.remove(Filter.ALL); - prepareUpdateWithOptions(joiningDate); - result = employeeRepository.find(); - assertEquals(result.size(), 2); - - Document update = createDocument(); - update.put("joinDate", newJoiningDate); - - writeResult = employeeRepository.update(where("joinDate").eq(joiningDate), update, false); - assertEquals(writeResult.getAffectedCount(), 2); - - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - - result = employeeRepository.find(where("joinDate").eq(newJoiningDate)); - assertEquals(result.size(), 2); - } - - @Test - public void testUpsertTrue() { - Date joiningDate = new Date(); - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("some road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(joiningDate); - Note empNote1 = new Note(); - empNote1.setNoteId(23L); - empNote1.setText("sample text note"); - employee.setEmployeeNote(empNote1); - - WriteResult writeResult - = employeeRepository.update(where("empId").eq(12), employee, true); - assertEquals(writeResult.getAffectedCount(), 1); - - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 1); - } - - @Test - public void testUpsertFalse() { - Date joiningDate = new Date(); - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("some road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(joiningDate); - Note empNote1 = new Note(); - empNote1.setNoteId(23L); - empNote1.setText("sample text note"); - employee.setEmployeeNote(empNote1); - - WriteResult writeResult - = employeeRepository.update(where("empId").eq(12), employee, false); - assertEquals(writeResult.getAffectedCount(), 0); - - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - } - - @Test - public void testDeleteFilterAndWithOutOption() { - Date joiningDate = new Date(); - prepareUpdateWithOptions(joiningDate); - - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 2); - - WriteResult writeResult = employeeRepository.remove(where("joinDate").eq(joiningDate)); - assertEquals(writeResult.getAffectedCount(), 2); - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - } - - @Test - public void testDeleteFilterAndWithOption() { - Date joiningDate = new Date(); - prepareUpdateWithOptions(joiningDate); - - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 2); - - WriteResult writeResult = employeeRepository.remove(where("joinDate").eq(joiningDate), true); - assertEquals(writeResult.getAffectedCount(), 1); - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 1); - } - - @Test - public void testEmployeeRecord() { - Iterable totalResult = employeeRepository.find(); - int occurrence = 0; - for (Employee employee : totalResult) { - if (employee.getEmployeeNote().getText().toLowerCase().contains("class aptent")) { - occurrence++; - } - } - - Cursor cursor = employeeRepository.find(where("employeeNote.text").text("Class aptent")); - assertEquals(cursor.size(), occurrence); - } - - @Test - public void testUpdateWithOptions() { - Employee employee = employeeRepository.find().firstOrNull(); - - Document update = createDocument(); - update.put("address", "new address"); - - WriteResult writeResult - = employeeRepository.update(where("empId").eq(employee.getEmpId()), update, false); - assertEquals(writeResult.getAffectedCount(), 1); - - Employee byId = employeeRepository.getById(employee.getEmpId()); - assertEquals(byId.getAddress(), "new address"); - assertEquals(byId.getEmpId(), employee.getEmpId()); - - update.put("address", "another address"); - employeeRepository.update(where("empId").eq(employee.getEmpId()), update); - - byId = employeeRepository.getById(employee.getEmpId()); - assertEquals(byId.getAddress(), "another address"); - assertEquals(byId.getEmpId(), employee.getEmpId()); - } - - @Test(expected = InvalidIdException.class) - public void testMultiUpdateWithObject() { - employeeRepository.remove(Filter.ALL); - - Date now = new Date(); - Employee employee1 = new Employee(); - employee1.setEmpId(1L); - employee1.setAddress("abcd"); - employee1.setJoinDate(now); - - Employee employee2 = new Employee(); - employee2.setEmpId(2L); - employee2.setAddress("xyz"); - employee2.setJoinDate(now); - employeeRepository.insert(employee1, employee2); - - Employee update = new Employee(); - update.setAddress("new address"); - - WriteResult writeResult - = employeeRepository.update(where("joinDate").eq(now), update, false); - assertEquals(writeResult.getAffectedCount(), 0); - } - - @Test - public void testUpdateNull() { - Employee employee = employeeRepository.find().firstOrNull(); - Employee newEmployee = new Employee(employee); - newEmployee.setJoinDate(null); - - Employee result = employeeRepository.find(where("empId").eq(employee.getEmpId())).firstOrNull(); - assertNotNull(result.getJoinDate()); - - WriteResult writeResult = employeeRepository.update(newEmployee, false); - assertEquals(writeResult.getAffectedCount(), 1); - - result = employeeRepository.find(where("empId").eq(employee.getEmpId())).firstOrNull(); - assertNull(result.getJoinDate()); - - // update with object filter and item and set id different - } - - @Test - public void testUpdateWithChangedId() { - Employee employee = employeeRepository.find().firstOrNull(); - Long oldId = employee.getEmpId(); - long count = employeeRepository.size(); - - Employee newEmployee = new Employee(employee); - newEmployee.setEmpId(50L); - - Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); - assertNotNull(result.getJoinDate()); - - WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); - assertEquals(writeResult.getAffectedCount(), 1); - - assertEquals(count, employeeRepository.size()); - Cursor cursor = employeeRepository.find(where("empId").eq(oldId)); - assertEquals(cursor.size(), 0); - } - - @Test(expected = InvalidIdException.class) - public void testUpdateWithNullId() { - Employee employee = employeeRepository.find().firstOrNull(); - Long oldId = employee.getEmpId(); - - Employee newEmployee = new Employee(employee); - newEmployee.setEmpId(null); - - Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); - assertNotNull(result.getJoinDate()); - - WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); - assertEquals(writeResult.getAffectedCount(), 1); - } - - @Test(expected = UniqueConstraintException.class) - public void testUpdateWithDuplicateId() { - Employee employee = employeeRepository.find().firstOrNull(); - Long oldId = employee.getEmpId(); - long count = employeeRepository.size(); - - Employee newEmployee = new Employee(employee); - newEmployee.setEmpId(5L); - - Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); - assertNotNull(result.getJoinDate()); - - WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); - assertEquals(writeResult.getAffectedCount(), 1); - - assertEquals(count, employeeRepository.size()); - Cursor cursor = employeeRepository.find(where("empId").eq(oldId)); - assertEquals(cursor.size(), 0); - } - - @Test - public void testUpdateWithObject() { - Employee employee = employeeRepository.find().firstOrNull(); - Employee newEmployee = new Employee(employee); - - Long id = employee.getEmpId(); - String address = employee.getAddress(); - newEmployee.setAddress("new address"); - - WriteResult writeResult = employeeRepository.update(newEmployee); - assertEquals(writeResult.getAffectedCount(), 1); - - Employee emp = employeeRepository.find(where("empId").eq(id)).firstOrNull(); - assertNotEquals(address, emp.getAddress()); - assertEquals(employee.getEmpId(), emp.getEmpId()); - assertEquals(employee.getJoinDate(), emp.getJoinDate()); - assertArrayEquals(employee.getBlob(), emp.getBlob()); - } - - @Test - public void testUpsertWithObject() { - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("some road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(new Date()); - Note empNote = new Note(); - empNote.setNoteId(23L); - empNote.setText("sample text note"); - employee.setEmployeeNote(empNote); - - WriteResult writeResult = employeeRepository.update(employee, false); - assertEquals(writeResult.getAffectedCount(), 0); - writeResult = employeeRepository.update(employee, true); - assertEquals(writeResult.getAffectedCount(), 1); - - Employee emp = employeeRepository.find(where("empId").eq(12L)).firstOrNull(); - assertEquals(emp, employee); - } - - @Test - public void testRemoveObject() { - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("some road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(new Date()); - Note empNote = new Note(); - empNote.setNoteId(23L); - empNote.setText("sample text note"); - employee.setEmployeeNote(empNote); - - long size = employeeRepository.size(); - - employeeRepository.insert(employee); - assertEquals(employeeRepository.size(), size + 1); - - employeeRepository.remove(employee); - assertEquals(employeeRepository.size(), size); - - Employee emp = employeeRepository.find(where("empId").eq(12L)).firstOrNull(); - assertNull(emp); - } - - private void prepareUpdateWithOptions(Date joiningDate) { - employeeRepository.remove(Filter.ALL); - - Employee employee1 = new Employee(); - employee1.setCompany(null); - employee1.setAddress("some road"); - employee1.setBlob(new byte[]{1, 2, 125}); - employee1.setEmpId(12L); - employee1.setJoinDate(joiningDate); - Note empNote1 = new Note(); - empNote1.setNoteId(23L); - empNote1.setText("sample text note"); - employee1.setEmployeeNote(empNote1); - - Employee employee2 = new Employee(); - employee2.setCompany(null); - employee2.setAddress("other road"); - employee2.setBlob(new byte[]{10, 12, 25}); - employee2.setEmpId(2L); - employee2.setJoinDate(joiningDate); - Note empNote2 = new Note(); - empNote2.setNoteId(2L); - empNote2.setText("some random note"); - employee2.setEmployeeNote(empNote2); - - employeeRepository.insert(employee1, employee2); - Cursor result = employeeRepository.find(); - assertEquals(result.size(), 2); - for (Employee e : result.project(Employee.class)) { - assertEquals(e.getJoinDate(), joiningDate); - } - } - - @Test - public void testUpdateWithDoc() { - Note note = new Note(); - note.setNoteId(10L); - note.setText("some note text"); - - Document document = createDocument("address", "some address") - .put("employeeNote", note); - - WriteResult result = employeeRepository.update(Filter.ALL, document); - assertEquals(result.getAffectedCount(), 10); - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/RepositorySearchTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/RepositorySearchTest.java deleted file mode 100644 index 8fac9d440..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/RepositorySearchTest.java +++ /dev/null @@ -1,593 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test; - -import lombok.Getter; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.exceptions.InvalidIdException; -import org.dizitart.no2.exceptions.NotIdentifiableException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.repository.Cursor; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.test.data.*; -import org.junit.Test; - -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.List; - -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.$; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class RepositorySearchTest extends BaseObjectRepositoryTest { - @Test - public void testFindWithOptions() { - Cursor cursor = employeeRepository.find().skipLimit(0, 1); - assertEquals(cursor.size(), 1); - assertNotNull(cursor.firstOrNull()); - } - - @Test - public void testEmployeeProjection() { - List employeeList = employeeRepository.find().toList(); - List subEmployeeList - = employeeRepository.find().project(SubEmployee.class).toList(); - - assertNotNull(employeeList); - assertNotNull(subEmployeeList); - - assertTrue(employeeList.size() > 0); - assertTrue(subEmployeeList.size() > 0); - - assertEquals(employeeList.size(), subEmployeeList.size()); - - for (int i = 0; i < subEmployeeList.size(); i++) { - Employee employee = employeeList.get(i); - SubEmployee subEmployee = subEmployeeList.get(i); - - assertEquals(employee.getEmpId(), subEmployee.getEmpId()); - assertEquals(employee.getJoinDate(), subEmployee.getJoinDate()); - assertEquals(employee.getAddress(), subEmployee.getAddress()); - } - - Cursor cursor = employeeRepository.find(); - assertNotNull(cursor.firstOrNull()); - assertNotNull(cursor.toString()); - assertEquals(cursor.toList().size(), employeeList.size()); - assertNotNull(cursor.firstOrNull()); - assertEquals(cursor.toList().size(), employeeList.size()); - } - - @Test - public void testEmptyResultProjection() { - employeeRepository.remove(ALL); - assertNull(employeeRepository.find().firstOrNull()); - - assertNull(employeeRepository.find(where("empId").eq(-1)) - .firstOrNull()); - } - - @Test - public void testGetById() { - ObjectRepository empRepo = db.getRepository(Employee.class); - Employee e1 = DataGenerator.generateEmployee(); - Employee e2 = DataGenerator.generateEmployee(); - Employee e3 = DataGenerator.generateEmployee(); - Employee e4 = DataGenerator.generateEmployee(); - - e1.setEmpId(1000000L); - e2.setEmpId(2000000L); - e3.setEmpId(3000000L); - e4.setEmpId(4000000L); - - empRepo.insert(e1, e2, e3, e4); - - Employee byId = empRepo.getById(2000000L); - assertEquals(byId, e2); - } - - @Test(expected = NotIdentifiableException.class) - public void testGetByIdNoId() { - ObjectRepository repository = db.getRepository(Note.class); - Note n1 = DataGenerator.randomNote(); - Note n2 = DataGenerator.randomNote(); - Note n3 = DataGenerator.randomNote(); - - assert n1 != null; - n1.setNoteId(1000000L); - assert n2 != null; - n2.setNoteId(2000000L); - assert n3 != null; - n3.setNoteId(3000000L); - - repository.insert(n1, n2, n3); - - repository.getById(2000000L); - } - - @Test(expected = InvalidIdException.class) - public void testGetByIdNullId() { - ObjectRepository empRepo = db.getRepository(Employee.class); - Employee e1 = DataGenerator.generateEmployee(); - Employee e2 = DataGenerator.generateEmployee(); - Employee e3 = DataGenerator.generateEmployee(); - Employee e4 = DataGenerator.generateEmployee(); - - e1.setEmpId(1000000L); - e2.setEmpId(2000000L); - e3.setEmpId(3000000L); - e4.setEmpId(4000000L); - - empRepo.insert(e1, e2, e3, e4); - - empRepo.getById(null); - } - - @Test(expected = InvalidIdException.class) - public void testGetByIdWrongType() { - ObjectRepository empRepo = db.getRepository(Employee.class); - Employee e1 = DataGenerator.generateEmployee(); - Employee e2 = DataGenerator.generateEmployee(); - Employee e3 = DataGenerator.generateEmployee(); - Employee e4 = DataGenerator.generateEmployee(); - - e1.setEmpId(1000000L); - e2.setEmpId(2000000L); - e3.setEmpId(3000000L); - e4.setEmpId(4000000L); - - empRepo.insert(e1, e2, e3, e4); - - Employee byId = empRepo.getById("employee"); - assertNull(byId); - } - - @Test - public void testEqualFilterById() { - Employee employee = employeeRepository.find().firstOrNull(); - long empId = employee.getEmpId(); - Employee emp = employeeRepository.find(where("empId").eq(empId)) - .project(Employee.class).firstOrNull(); - assertEquals(employee, emp); - } - - @Test - public void testEqualFilter() { - Employee employee = employeeRepository.find() - .firstOrNull(); - - Employee emp = employeeRepository.find(where("joinDate").eq(employee.getJoinDate())) - .project(Employee.class) - .firstOrNull(); - assertEquals(employee, emp); - } - - @Test - public void testStringEqualFilter() { - ObjectRepository repository = db.getRepository(ProductScore.class); - - ProductScore object = new ProductScore(); - object.setProduct("test"); - object.setScore(1); - repository.insert(object); - - object = new ProductScore(); - object.setProduct("test"); - object.setScore(2); - repository.insert(object); - - object = new ProductScore(); - object.setProduct("another-test"); - object.setScore(3); - repository.insert(object); - - assertEquals(repository.find(where("product").eq("test")).size(), 2); - } - - @Test - public void testAndFilter() { - Employee emp = employeeRepository.find().firstOrNull(); - - long id = emp.getEmpId(); - String address = emp.getAddress(); - Date joinDate = emp.getJoinDate(); - - Employee employee = employeeRepository.find( - where("empId").eq(id) - .and( - where("address").regex(address) - .and( - where("joinDate").eq(joinDate)))).firstOrNull(); - - assertEquals(emp, employee); - } - - @Test - public void testOrFilter() { - Employee emp = employeeRepository.find().firstOrNull(); - long id = emp.getEmpId(); - - Employee employee = employeeRepository.find( - where("empId").eq(id) - .or( - where("address").regex("n/a") - .or( - where("joinDate").eq(null)))).firstOrNull(); - - assertEquals(emp, employee); - } - - @Test - public void testNotFilter() { - Employee emp = employeeRepository.find().firstOrNull(); - long id = emp.getEmpId(); - - Employee employee = employeeRepository.find( - where("empId").eq(id).not()).firstOrNull(); - assertNotEquals(emp, employee); - } - - @Test - public void testGreaterFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Ascending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").gt(id)) - .toList(); - - assertFalse(employeeList.contains(emp)); - assertEquals(employeeList.size(), 9); - } - - @Test - public void testGreaterEqualFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Ascending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").gte(id)) - .toList(); - - assertTrue(employeeList.contains(emp)); - assertEquals(employeeList.size(), 10); - } - - @Test - public void testLesserThanFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Descending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").lt(id)) - .toList(); - - assertFalse(employeeList.contains(emp)); - assertEquals(employeeList.size(), 9); - } - - @Test - public void testLesserEqualFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Descending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").lte(id)) - .toList(); - - assertTrue(employeeList.contains(emp)); - assertEquals(employeeList.size(), 10); - } - - @Test - public void testTextFilter() { - Employee emp = employeeRepository.find().firstOrNull(); - String text = emp.getEmployeeNote().getText(); - - List employeeList = employeeRepository.find(where("employeeNote.text").text(text)) - .toList(); - - assertTrue(employeeList.contains(emp)); - } - - @Test - public void testRegexFilter() { - RecordStream employees = employeeRepository.find(); - int count = employees.toList().size(); - - List employeeList = employeeRepository.find(where("employeeNote.text").regex(".*")) - .toList(); - - assertEquals(employeeList.size(), count); - } - - @Test - public void testInFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Descending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").in(id, id - 1, id - 2)) - .toList(); - - assertTrue(employeeList.contains(emp)); - assertEquals(employeeList.size(), 3); - - employeeList = employeeRepository.find(where("empId").in(id - 1, id - 2)).toList(); - assertEquals(employeeList.size(), 2); - } - - @Test - public void testNotInFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Descending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").notIn(id, id - 1, id - 2)) - .toList(); - - assertFalse(employeeList.contains(emp)); - assertEquals(employeeList.size(), 7); - - employeeList = employeeRepository.find(where("empId").notIn(id - 1, id - 2)).toList(); - assertEquals(employeeList.size(), 8); - } - - @Test - public void testElemMatchFilter() { - final ProductScore score1 = new ProductScore("abc", 10); - final ProductScore score2 = new ProductScore("abc", 8); - final ProductScore score3 = new ProductScore("abc", 7); - final ProductScore score4 = new ProductScore("xyz", 5); - final ProductScore score5 = new ProductScore("xyz", 7); - final ProductScore score6 = new ProductScore("xyz", 8); - - ObjectRepository repository = db.getRepository(ElemMatch.class); - ElemMatch e1 = new ElemMatch() {{ - setId(1); - setStrArray(new String[]{"a", "b"}); - setProductScores(new ProductScore[]{score1, score4}); - }}; - ElemMatch e2 = new ElemMatch() {{ - setId(2); - setStrArray(new String[]{"d", "e"}); - setProductScores(new ProductScore[]{score2, score5}); - }}; - ElemMatch e3 = new ElemMatch() {{ - setId(3); - setStrArray(new String[]{"a", "f"}); - setProductScores(new ProductScore[]{score3, score6}); - }}; - - repository.insert(e1, e2, e3); - - List elements = repository.find( - where("productScores").elemMatch( - where("product").eq("xyz") - .and(where("score").gte(8)))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("score").lte(8).not())).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("product").eq("xyz") - .or(where("score").gte(8)))).toList(); - assertEquals(elements.size(), 3); - - elements = repository.find( - where("productScores").elemMatch( - where("product").eq("xyz"))).toList(); - assertEquals(elements.size(), 3); - - elements = repository.find( - where("productScores").elemMatch( - where("score").gte(10))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("score").gt(8))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("score").lt(7))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("score").lte(7))).toList(); - assertEquals(elements.size(), 3); - - elements = repository.find( - where("productScores").elemMatch( - where("score").in(7, 8))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find( - where("productScores").elemMatch( - where("score").notIn(7, 8))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("product").regex("xyz"))).toList(); - assertEquals(elements.size(), 3); - - elements = repository.find(where("strArray").elemMatch($.eq("a"))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find( - where("strArray").elemMatch( - $.eq("a") - .or($.eq("f") - .or($.eq("b"))).not())).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find(where("strArray").elemMatch($.gt("e"))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find(where("strArray").elemMatch($.gte("e"))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find(where("strArray").elemMatch($.lte("b"))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find(where("strArray").elemMatch($.lt("a"))).toList(); - assertEquals(elements.size(), 0); - - elements = repository.find(where("strArray").elemMatch($.in("a", "f"))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find(where("strArray").elemMatch($.regex("a"))).toList(); - assertEquals(elements.size(), 2); - } - - @Test - public void testFilterAll() { - ObjectRepository repository = db.getRepository(ElemMatch.class); - Cursor cursor = repository.find(ALL); - assertNotNull(cursor); - assertEquals(cursor.size(), 0); - - repository.insert(new ElemMatch()); - cursor = repository.find(ALL); - assertNotNull(cursor); - assertEquals(cursor.size(), 1); - } - - @Test - public void testEqualsOnTextIndex() { - PersonEntity p1 = new PersonEntity("jhonny"); - PersonEntity p2 = new PersonEntity("jhonny"); - PersonEntity p3 = new PersonEntity("jhonny"); - - ObjectRepository repository = db.getRepository(PersonEntity.class); - repository.insert(p1); - repository.insert(p2); - repository.insert(p3); - - List sameNamePeople = repository.find(where("name").eq("jhonny")).toList(); - assertEquals(sameNamePeople.size(), 3); - - sameNamePeople = repository.find(where("name").eq("JHONNY")).toList(); - assertEquals(sameNamePeople.size(), 0); - - sameNamePeople = repository.find(where("name").text("jhonny")).toList(); - assertEquals(sameNamePeople.size(), 3); - - sameNamePeople = repository.find(where("name").text("JHONNY")).toList(); - assertEquals(sameNamePeople.size(), 3); - - sameNamePeople = repository.find(where("name").eq("jhon*")).toList(); - assertEquals(sameNamePeople.size(), 0); - - sameNamePeople = repository.find(where("name").text("jhon*")).toList(); - assertEquals(sameNamePeople.size(), 3); - } - - @Test - public void testIssue62() { - PersonEntity p1 = new PersonEntity("abcd"); - p1.setStatus("Married"); - - PersonEntity p2 = new PersonEntity("efgh"); - p2.setStatus("Married"); - - PersonEntity p3 = new PersonEntity("ijkl"); - p3.setStatus("Un-Married"); - - ObjectRepository repository = db.getRepository(PersonEntity.class); - repository.insert(p1); - repository.insert(p2); - repository.insert(p3); - - Filter married = where("status").eq("Married"); - - assertEquals(repository.find(married).size(), 2); - assertEquals(repository.find(married).sort("status", SortOrder.Descending).size(), 2); - - assertEquals(repository.find().sort("status", SortOrder.Descending).firstOrNull().getStatus(), "Un-Married"); - - assertEquals(repository.find().sort("status", SortOrder.Ascending).size(), 3); - assertEquals(repository.find().sort("status", SortOrder.Ascending).firstOrNull().getStatus(), "Married"); - } - - @Test - public void testRepeatableIndexAnnotation() { - ObjectRepository repo = db.getRepository(RepeatableIndexTest.class); - RepeatableIndexTest first = new RepeatableIndexTest(); - first.setAge(12); - first.setFirstName("fName"); - first.setLastName("lName"); - repo.insert(first); - - assertTrue(repo.hasIndex("firstName")); - assertTrue(repo.hasIndex("age")); - assertTrue(repo.hasIndex("lastName")); - - assertEquals(repo.find(where("age").eq(12)).firstOrNull(), first); - } - - @Test - public void testIdSet() { - Cursor employees = employeeRepository.find().sort("empId", SortOrder.Ascending); - assertEquals(employees.size(), 10); - } - - @Test - public void testBetweenFilter() { - @Getter - class TestData { - private final Date age; - - public TestData(Date age) { - this.age = age; - } - } - - TestData data1 = new TestData(new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime()); - TestData data2 = new TestData(new GregorianCalendar(2021, Calendar.FEBRUARY, 12).getTime()); - TestData data3 = new TestData(new GregorianCalendar(2022, Calendar.MARCH, 13).getTime()); - TestData data4 = new TestData(new GregorianCalendar(2023, Calendar.APRIL, 14).getTime()); - TestData data5 = new TestData(new GregorianCalendar(2024, Calendar.MAY, 15).getTime()); - TestData data6 = new TestData(new GregorianCalendar(2025, Calendar.JUNE, 16).getTime()); - - ObjectRepository repository = db.getRepository(TestData.class); - repository.insert(data1, data2, data3, data4, data5, data6); - - Cursor cursor = repository.find(where("age").between( - new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), - new GregorianCalendar(2025, Calendar.JUNE, 16).getTime())); - assertEquals(cursor.size(), 6); - - cursor = repository.find(where("age").between( - new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), - new GregorianCalendar(2025, Calendar.JUNE, 16).getTime(), false)); - assertEquals(cursor.size(), 4); - - cursor = repository.find(where("age").between( - new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), - new GregorianCalendar(2025, Calendar.JUNE, 16).getTime(), false, true)); - assertEquals(cursor.size(), 5); - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/Retry.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/Retry.java deleted file mode 100644 index 62d667b49..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/Retry.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.dizitart.no2.test; - -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; - -/** - * @author Anindya Chatterjee - */ -public class Retry implements TestRule { - private final int retryCount; - - public Retry(int retryCount) { - this.retryCount = retryCount; - } - - public Statement apply(Statement base, Description description) { - return statement(base, description); - } - - private Statement statement(final Statement base, final Description description) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - Throwable caughtThrowable = null; - - // implement retry logic here - for (int i = 0; i < retryCount; i++) { - try { - base.evaluate(); - return; - } catch (Throwable t) { - caughtThrowable = t; - System.err.println(description.getDisplayName() + ": run " + (i + 1) + " failed"); - } - } - System.err.println(description.getDisplayName() + ": giving up after " + retryCount + " failures"); - throw caughtThrowable; - } - }; - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/TestUtil.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/TestUtil.java deleted file mode 100644 index a38627408..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/TestUtil.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2019-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test; - -import lombok.extern.slf4j.Slf4j; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.module.NitriteModule; -import org.dizitart.no2.mvstore.MVStoreModule; - -/** - * @author Anindya Chatterjee - */ -@Slf4j -public class TestUtil { - - public static Nitrite createDb(NitriteModule module) { - MVStoreModule storeModule = MVStoreModule.withConfig() - .build(); - - return Nitrite.builder() - .loadModule(storeModule) - .loadModule(module) - .fieldSeparator(".") - .openOrCreate(); - } - - public static Nitrite createDb(String user, String password, NitriteModule module) { - MVStoreModule storeModule = MVStoreModule.withConfig() - .build(); - - return Nitrite.builder() - .loadModule(storeModule) - .loadModule(module) - .fieldSeparator(".") - .openOrCreate(user, password); - } - - public static Nitrite createDb(String filePath, NitriteModule module) { - return Nitrite.builder() - .loadModule(new MVStoreModule(filePath)) - .loadModule(module) - .fieldSeparator(".") - .openOrCreate(); - } - - public static Nitrite createDb(String filePath, String user, String password, NitriteModule module) { - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(filePath) - .compress(true) - .build(); - - return Nitrite.builder() - .loadModule(storeModule) - .loadModule(module) - .fieldSeparator(".") - .openOrCreate(user, password); - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/UnAnnotatedObjectTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/UnAnnotatedObjectTest.java deleted file mode 100644 index 10a259194..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/UnAnnotatedObjectTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test; - -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.repository.Cursor; -import org.dizitart.no2.test.data.ClassA; -import org.dizitart.no2.test.data.ClassC; -import org.junit.Test; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -/** - * @author Anindya Chatterjee. - */ -public class UnAnnotatedObjectTest extends BaseObjectRepositoryTest { - - @Test - public void testFind() { - Cursor cursor = aObjectRepository.find(); - assertEquals(cursor.size(), 10); - assertFalse(cursor.isEmpty()); - - IndexOptions indexOptions = new IndexOptions(); - indexOptions.setIndexType(IndexType.Unique); - aObjectRepository.createIndex("b.number", indexOptions); - - cursor = aObjectRepository.find(where("b.number").eq(160).not()). - sort("b.number", SortOrder.Ascending).skipLimit(0, 10); - - System.out.println("Available - " + !cursor.isEmpty()); - System.out.println("Total Size - " + cursor.size()); - - Iterable findRecord = cursor.project(ClassA.class); - for (ClassA classA : findRecord) { - System.out.println(classA); - } - - cursor = aObjectRepository.find(where("b.number").eq(160).not()). - sort("b.number", SortOrder.Descending).skipLimit(2, 7); - - System.out.println("Available - " + !cursor.isEmpty()); - System.out.println("Total Size - " + cursor.size()); - - findRecord = cursor.project(ClassA.class); - for (ClassA classA : findRecord) { - System.out.println(classA); - } - - Cursor cursor2 = cObjectRepository.find(where("id").gt(900)). - sort("id", SortOrder.Descending).skipLimit(2, 7); - System.out.println("Available - " + !cursor2.isEmpty()); - System.out.println("Total Size - " + cursor2.size()); - - Iterable findRecordC = cursor2.project(ClassC.class); - for (ClassC classC : findRecordC) { - System.out.println(classC); - } - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/UniversalTextTokenizerTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/UniversalTextTokenizerTest.java deleted file mode 100644 index 8e39782af..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/UniversalTextTokenizerTest.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.index.NitriteTextIndexer; -import org.dizitart.no2.index.fulltext.Languages; -import org.dizitart.no2.index.fulltext.UniversalTextTokenizer; -import org.dizitart.no2.mapper.JacksonMapperModule; -import org.dizitart.no2.mvstore.MVStoreModule; -import org.dizitart.no2.mvstore.MVStoreModuleBuilder; -import org.dizitart.no2.repository.Cursor; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; - -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.module.NitriteModule.module; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -/** - * @author Anindya Chatterjee - */ -public class UniversalTextTokenizerTest extends BaseObjectRepositoryTest { - private final String fileName = getRandomTempDbFile(); - private ObjectRepository textRepository; - - @Before - @Override - public void setUp() { - openDb(); - - textRepository = db.getRepository(TextData.class); - - for (int i = 0; i < 10; i++) { - TextData data = new TextData(); - data.id = i; - if (i % 2 == 0) { - data.text = "তারা বলল, “এস আমরা আমাদের জন্যে এক বড় শহর বানাই| আর এমন একটি উঁচু স্তম্ভ বানাই " + - "যা আকাশ স্পর্শ করবে| তাহলে আমরা বিখ্যাত হব এবং এটা আমাদের এক সঙ্গে ধরে রাখবে| সারা পৃথিবীতে " + - "আমরা ছড়িয়ে থাকব না|”"; - } else if (i % 3 == 0) { - data.text = "部汁楽示時葉没式将場参右属。覧観将者雄日語山銀玉襲政著約域費。新意虫跡更味株付安署審完顔団。" + - "困更表転定一史賀面政巣迎文学豊税乗。白間接特時京転閉務講封新内。側流効表害場測投活聞秀職探画労。" + - "福川順式極木注美込行警検直性禁遅。土一詳非物質紙姿漢人内池銀周街躍澹二。平討聞述並時全経詳業映回作朝送恵時。"; - } else if (i % 5 == 0) { - data.text = " أقبل لسفن العالم، في أما, بـ بال أملاً الثالث،. الذود بالرّد الثالث، مع" + - " قام, كردة الضغوط الإمداد أن وصل. ٠٨٠٤ عُقر انتباه يكن قد, أن زهاء وفنلندا بال. لان ما يقوم المعاهدات," + - " بـ بخطوط استعملت عدد. صفحة لفشل ولاتّساع لم قام, في مكثّفة الكونجرس جعل, الثالث، واقتصار دون ان.\n"; - } else { - data.text = "Lorem ipsum dolor sit amet, nobis audire perpetua eu sea. Te semper causae " + - "efficiantur per. Qui affert dolorum at. Mel tale constituto interesset in."; - } - textRepository.insert(data); - } - } - - @After - @Override - public void clear() throws IOException { - if (textRepository != null && !textRepository.isDropped()) { - textRepository.remove(ALL); - } - - if (db != null) { - db.commit(); - db.close(); - } - - if (!inMemory) { - Files.delete(Paths.get(fileName)); - } - } - - private void openDb() { - MVStoreModuleBuilder builder = MVStoreModule.withConfig(); - - if (isCompressed) { - builder.compress(true); - } - - if (!isAutoCommit) { - builder.autoCommit(false); - } - - if (!inMemory) { - builder.filePath(fileName); - } - - MVStoreModule storeModule = builder.build(); - NitriteBuilder nitriteBuilder = Nitrite.builder() - .fieldSeparator(".") - .loadModule(storeModule); - - nitriteBuilder.loadModule(new JacksonMapperModule()); - - UniversalTextTokenizer tokenizer; - if (isCompressed) { - tokenizer = new UniversalTextTokenizer(Languages.Bengali, Languages.Chinese, Languages.English); - } else { - tokenizer = new UniversalTextTokenizer(Languages.ALL); - } - nitriteBuilder.loadModule(module(new NitriteTextIndexer(tokenizer))); - - if (isProtected) { - db = nitriteBuilder.openOrCreate("test-user", "test-password"); - } else { - db = nitriteBuilder.openOrCreate(); - } - } - - @Test - public void testUniversalFullTextIndexing() { - Cursor cursor = textRepository.find(where("text").text("Lorem")); - assertEquals(cursor.size(), 2); - for (TextData data : cursor) { - System.out.println("Id for English text -> " + data.id); - if (data.id % 2 == 0 || data.id % 3 == 0 || data.id % 5 == 0) { - fail(); - } - } - - cursor = textRepository.find(where("text").text("শহর")); - assertEquals(cursor.size(), 5); - for (TextData data : cursor) { - System.out.println("Id for Bengali text -> " + data.id); - if (data.id % 2 != 0) { - fail(); - } - } - - cursor = textRepository.find(where("text").text("転閉")); - assertEquals(cursor.size(), 0); - cursor = textRepository.find(where("text").text("*転閉*")); - assertEquals(cursor.size(), 2); - for (TextData data : cursor) { - System.out.println("Id for Chinese text -> " + data.id); - if (data.id % 3 != 0) { - fail(); - } - } - - cursor = textRepository.find(where("text").text("أقبل")); - if (isCompressed) { - assertEquals(cursor.size(), 1); - for (TextData data : cursor) { - System.out.println("Id for Arabic text -> " + data.id); - if (data.id % 5 != 0) { - fail(); - } - } - } else { - // أقبل eliminated as stop word - assertEquals(cursor.size(), 0); - } - } - - @Indices( - @Index(value = "text", type = IndexType.Fulltext) - ) - public static class TextData { - public int id; - public String text; - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ChildClass.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ChildClass.java deleted file mode 100644 index 512d73cd1..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ChildClass.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.repository.annotations.InheritIndices; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@InheritIndices -public class ChildClass extends ParentClass { - private String name; -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ClassA.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ClassA.java deleted file mode 100644 index cd5a9a1dc..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ClassA.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; - -import java.util.UUID; - -@EqualsAndHashCode -@ToString -public class ClassA { - @Getter - @Setter - private ClassB classB; - @Getter - @Setter - private UUID uid; - @Getter - @Setter - private String string; - @Getter - @Setter - private byte[] blob; - - public static ClassA create(int seed) { - ClassB classB = ClassB.create(seed); - ClassA classA = new ClassA(); - classA.classB = classB; - classA.uid = new UUID(seed, seed + 50); - classA.string = Integer.toHexString(seed); - classA.blob = new byte[]{(byte) seed}; - return classA; - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ClassB.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ClassB.java deleted file mode 100644 index 328967d74..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ClassB.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; - -@EqualsAndHashCode -@ToString -class ClassB implements Comparable { - @Getter - @Setter - private int number; - @Getter - @Setter - private String text; - - static ClassB create(int seed) { - ClassB classB = new ClassB(); - classB.setNumber(seed + 100); - classB.setText(Integer.toBinaryString(seed)); - return classB; - } - - @Override - public int compareTo(ClassB o) { - return Integer.compare(number, o.number); - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ClassC.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ClassC.java deleted file mode 100644 index fb9f2034c..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ClassC.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; - -@EqualsAndHashCode -@ToString -public class ClassC { - @Getter - @Setter - private long id; - @Getter - @Setter - private double digit; - @Getter - @Setter - private ClassA parent; - - public static ClassC create(int seed) { - ClassC classC = new ClassC(); - classC.id = seed * 5000; - classC.digit = seed * 69.65; - classC.parent = ClassA.create(seed); - return classC; - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/Company.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/Company.java deleted file mode 100644 index 364433bae..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/Company.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; - -import java.io.Serializable; -import java.util.Date; -import java.util.List; -import java.util.Map; - -/** - * @author Anindya Chatterjee. - */ -@ToString -@EqualsAndHashCode -@Indices({ - @Index(value = "companyName") -}) -public class Company implements Serializable { - @Id - @Getter - @Setter - private Long companyId; - - @Getter - @Setter - private String companyName; - - @Getter - @Setter - private Date dateCreated; - - @Getter - @Setter - private List departments; - - @Getter - @Setter - private Map> employeeRecord; -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/DataGenerator.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/DataGenerator.java deleted file mode 100644 index e3d306bda..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/DataGenerator.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.experimental.UtilityClass; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @author Anindya Chatterjee. - */ -@UtilityClass -public class DataGenerator { - private static Random random = new Random(System.currentTimeMillis()); - private static AtomicInteger counter = new AtomicInteger(random.nextInt()); - - public static Company generateCompanyRecord() { - Company company = new Company(); - company.setCompanyId(System.nanoTime() + counter.incrementAndGet()); - company.setCompanyName(randomCompanyName()); - company.setDateCreated(randomDate()); - List departments = departments(); - company.setDepartments(departments); - - Map> employeeRecord = new HashMap<>(); - for (String department : departments) { - employeeRecord.put(department, - generateEmployeeRecords(company, random.nextInt(20))); - } - company.setEmployeeRecord(employeeRecord); - return company; - } - - private static List generateEmployeeRecords(Company company, int count) { - List employeeList = new ArrayList<>(); - for (int i = 0; i < count; i++) { - Employee employee = generateEmployee(); - employee.setCompany(company); - employeeList.add(employee); - } - return employeeList; - } - - public static Employee generateEmployee() { - Employee employee = new Employee(); - employee.setEmpId(System.nanoTime() + counter.incrementAndGet()); - employee.setJoinDate(randomDate()); - employee.setAddress(UUID.randomUUID().toString().replace('-', ' ')); - - byte[] blob = new byte[random.nextInt(8000)]; - random.nextBytes(blob); - employee.setBlob(blob); - employee.setEmployeeNote(randomNote()); - - return employee; - } - - private static Date randomDate() { - return new Date(-946771200000L + - (Math.abs(random.nextLong()) % (70L * 365 * 24 * 60 * 60 * 1000))); - } - - public static Note randomNote() { - InputStream inputStream = ClassLoader.getSystemResourceAsStream("test.text"); - BufferedReader br = new BufferedReader(new InputStreamReader(inputStream)); - - String strLine; - long line = random.nextInt(49); - int count = 0; - try { - while ((strLine = br.readLine()) != null) { - if (count == line) { - Note note = new Note(); - note.setNoteId(line); - note.setText(strLine); - return note; - } - count++; - } - } catch (IOException e) { - // ignore - } finally { - try { - br.close(); - } catch (IOException e) { - // ignore - } - } - return null; - } - - private static String randomCompanyName() { - InputStream inputStream = ClassLoader.getSystemResourceAsStream("english.stop"); - - assert inputStream != null; - try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) { - String strLine; - int line = random.nextInt(570); - int count = 0; - while ((strLine = br.readLine()) != null) { - if (count == line) { - return strLine + System.nanoTime() + " inc."; - } - count++; - } - } catch (IOException e) { - // ignore - } - // ignore - return null; - } - - private static List departments() { - return new ArrayList() {{ - add("dev"); - add("hr"); - add("qa"); - add("dev-ops"); - add("sales"); - add("marketing"); - add("design"); - add("support"); - }}; - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ElemMatch.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ElemMatch.java deleted file mode 100644 index 992fdf906..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ElemMatch.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.Data; - -/** - * @author Anindya Chatterjee - */ -@Data -public class ElemMatch { - private long id; - private String[] strArray; - private ProductScore[] productScores; -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/Employee.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/Employee.java deleted file mode 100644 index 7a68458d9..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/Employee.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; - -import java.io.Serializable; -import java.util.Date; - -/** - * @author Anindya Chatterjee. - */ -@ToString -@EqualsAndHashCode -@Indices({ - @Index(value = "joinDate", type = IndexType.NonUnique), - @Index(value = "address", type = IndexType.Fulltext), - @Index(value = "employeeNote.text", type = IndexType.Fulltext) -}) -public class Employee implements Serializable { - @Id - @Getter - @Setter - private Long empId; - - @Getter - @Setter - private Date joinDate; - - @Getter - @Setter - private String address; - - @Getter - @Setter - private transient Company company; - - @Getter - @Setter - private byte[] blob; - - @Getter - @Setter - private Note employeeNote; - - public Employee() { - } - - public Employee(Employee copy) { - empId = copy.empId; - joinDate = copy.joinDate; - address = copy.address; - company = copy.company; - blob = copy.blob; - employeeNote = copy.employeeNote; - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/Note.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/Note.java deleted file mode 100644 index 5eba9a8a9..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/Note.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; - -import java.io.Serializable; - -/** - * @author Anindya Chatterjee. - */ -@EqualsAndHashCode -public class Note implements Serializable { - @Getter - @Setter - private Long noteId; - @Getter - @Setter - private String text; -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ParentClass.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ParentClass.java deleted file mode 100644 index 4d5a16772..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ParentClass.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; - -import java.util.Date; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@Indices( - @Index(value = "date") -) -public class ParentClass extends SuperDuperClass { - @Id - protected Long id; - private Date date; -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/PersonEntity.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/PersonEntity.java deleted file mode 100644 index 195f5d49b..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/PersonEntity.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.Data; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; - -import java.util.Date; -import java.util.UUID; - -/** - * @author Anindya Chatterjee - */ -@Data -@Indices({ - @Index(value = "name", type = IndexType.Fulltext) -}) -public class PersonEntity { - @Id - private String uuid; - private String name; - private String status; - private PersonEntity friend; - private Date dateCreated; - - public PersonEntity() { - this.uuid = UUID.randomUUID().toString(); - this.dateCreated = new Date(); - } - - public PersonEntity(String name) { - this.uuid = UUID.randomUUID().toString(); - this.name = name; - this.dateCreated = new Date(); - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ProductScore.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ProductScore.java deleted file mode 100644 index 0faca8005..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/ProductScore.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.Getter; -import lombok.Setter; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -public class ProductScore { - private String product; - private int score; - - public ProductScore() { - } - - public ProductScore(String product, int score) { - this.product = product; - this.score = score; - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/RepeatableIndexTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/RepeatableIndexTest.java deleted file mode 100644 index 1da0b894f..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/RepeatableIndexTest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.Data; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.repository.annotations.Index; - -/** - * @author Anindya Chatterjee - */ -@Data -@Index(value = "firstName") -@Index(value = "age", type = IndexType.NonUnique) -@Index(value = "lastName", type = IndexType.Fulltext) -public class RepeatableIndexTest { - private String firstName; - private Integer age; - private String lastName; -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/StressRecord.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/StressRecord.java deleted file mode 100644 index 3c7e0eebc..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/StressRecord.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.Getter; -import lombok.Setter; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class StressRecord { - private String firstName; - private boolean processed; - private String lastName; - private boolean failed; - private String notes; -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/SubEmployee.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/SubEmployee.java deleted file mode 100644 index 808c2c7de..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/SubEmployee.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; - -import java.util.Date; - -/** - * @author Anindya Chatterjee. - */ -@EqualsAndHashCode -public class SubEmployee { - @Getter - @Setter - private Long empId; - - @Getter - @Setter - private Date joinDate; - - @Getter - @Setter - private String address; -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/SuperDuperClass.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/SuperDuperClass.java deleted file mode 100644 index e1bab1eb5..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/SuperDuperClass.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.repository.annotations.Index; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@Index(value = "text", type = IndexType.Fulltext) -public class SuperDuperClass { - private String text; -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithCircularReference.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithCircularReference.java deleted file mode 100644 index 15e8e8128..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithCircularReference.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithCircularReference { - @Id - private String name; - private WithCircularReference parent; -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithClassField.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithClassField.java deleted file mode 100644 index 6dbc86332..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithClassField.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithClassField { - @Id - private String name; - private Class clazz; -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithCustomConstructor.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithCustomConstructor.java deleted file mode 100644 index 843f49c2f..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithCustomConstructor.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithCustomConstructor { - @Id - private String name; - private long number; - - public WithCustomConstructor(String name, long number) { - this.name = name; - this.number = number; - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithDateId.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithDateId.java deleted file mode 100644 index de502257d..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithDateId.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; - -import java.util.Date; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@EqualsAndHashCode -public class WithDateId { - private Date id; - private String name; -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithEmptyStringId.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithEmptyStringId.java deleted file mode 100644 index d95053ced..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithEmptyStringId.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithEmptyStringId { - @Id - private String name; -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithFinalField.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithFinalField.java deleted file mode 100644 index 2c9c19fe6..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithFinalField.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.Getter; -import lombok.Setter; - -/** - * @author Anindya Chatterjee. - */ -@Getter -public class WithFinalField { - private final long number; - @Setter - private String name; - - public WithFinalField() { - number = 2; - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithNullId.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithNullId.java deleted file mode 100644 index 0136adebf..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithNullId.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithNullId { - @Id - private String name; - private long number; -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithObjectId.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithObjectId.java deleted file mode 100644 index ad71e12a7..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithObjectId.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithObjectId { - @Id - private WithOutId withOutId; -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithOutGetterSetter.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithOutGetterSetter.java deleted file mode 100644 index 41c775390..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithOutGetterSetter.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.EqualsAndHashCode; - -/** - * @author Anindya Chatterjee. - */ -@EqualsAndHashCode -public class WithOutGetterSetter { - private String name; - private long number; - - public WithOutGetterSetter() { - name = "test"; - number = 2; - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithOutId.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithOutId.java deleted file mode 100644 index 009aadf25..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithOutId.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.Getter; -import lombok.Setter; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithOutId implements Comparable { - private String name; - private long number; - - @Override - public int compareTo(WithOutId o) { - return Long.compare(number, o.number); - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithPrivateConstructor.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithPrivateConstructor.java deleted file mode 100644 index 6f782e5f0..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithPrivateConstructor.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.EqualsAndHashCode; - -/** - * @author Anindya Chatterjee. - */ -@EqualsAndHashCode -public class WithPrivateConstructor { - private String name; - private long number; - - private WithPrivateConstructor() { - name = "test"; - number = 2; - } - - public static WithPrivateConstructor create(final String name, final long number) { - WithPrivateConstructor obj = new WithPrivateConstructor(); - obj.number = number; - obj.name = name; - return obj; - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithPublicField.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithPublicField.java deleted file mode 100644 index d6bf5016e..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithPublicField.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -public class WithPublicField { - @Id - public String name; - public long number; -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithTransientField.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithTransientField.java deleted file mode 100644 index 862559e1b..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/data/WithTransientField.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithTransientField { - private transient String name; - @Id - private long number; -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/migrate/MigrationTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/migrate/MigrationTest.java deleted file mode 100644 index 504fc4551..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/migrate/MigrationTest.java +++ /dev/null @@ -1,571 +0,0 @@ -package org.dizitart.no2.test.migrate; - -import com.github.javafaker.Faker; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.Constants; -import org.dizitart.no2.exceptions.MigrationException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.JacksonMapperModule; -import org.dizitart.no2.migration.Instruction; -import org.dizitart.no2.migration.Migration; -import org.dizitart.no2.migration.TypeConverter; -import org.dizitart.no2.mvstore.MVStoreModule; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.test.Retry; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.UUID; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.test.BaseObjectRepositoryTest.getRandomTempDbFile; -import static org.dizitart.no2.test.TestUtil.createDb; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -public class MigrationTest { - private final String dbPath = getRandomTempDbFile(); - private Nitrite db; - private Faker faker; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - db = createDb(dbPath, new JacksonMapperModule()); - faker = new Faker(); - } - - @After - public void cleanUp() throws IOException { - if (!db.isClosed()) { - db.close(); - } - - Files.delete(Paths.get(dbPath)); - } - - @Test - public void testRepositoryMigrate() { - ObjectRepository oldRepo = db.getRepository(OldClass.class, "demo1"); - for (int i = 0; i < 10; i++) { - OldClass old = new OldClass(); - old.setEmpId(String.valueOf(faker.number().randomNumber())); - old.setFirstName(faker.name().firstName()); - old.setLastName(faker.name().lastName()); - old.setUuid(UUID.randomUUID().toString()); - - OldClass.Literature literature = new OldClass.Literature(); - literature.setRatings((float) faker.number().randomDouble(2, 1, 5)); - literature.setText(faker.lorem().paragraph()); - old.setLiterature(literature); - - oldRepo.insert(old); - } - - db.close(); - - Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { - @Override - public void migrate(Instruction instruction) { - instruction.forDatabase() - .addPassword("test-user", "test-password"); - - instruction.forRepository(OldClass.class, "demo1") - .renameRepository("new", null) - .changeDataType("empId", (TypeConverter) Long::parseLong) - .changeIdField("uuid", "empId") - .deleteField("uuid") - .renameField("lastName", "familyName") - .addField("fullName", document -> document.get("firstName", String.class) + " " - + document.get("familyName", String.class)) - .dropIndex("firstName") - .dropIndex("literature.text") - .changeDataType("literature.ratings", (TypeConverter) Math::round); - } - }; - - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compress(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate("test-user", "test-password"); - - ObjectRepository newRepo = db.getRepository(NewClass.class); - assertEquals(newRepo.size(), 10); - assertTrue(db.listCollectionNames().isEmpty()); - assertTrue(db.listKeyedRepository().isEmpty()); - - assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 2); - } - - @Test - public void testCollectionMigrate() { - NitriteCollection collection = db.getCollection("test"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - document.put("bloodGroup", faker.name().bloodGroup()); - document.put("age", faker.number().randomDigit()); - - collection.insert(document); - } - - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.NonUnique)); - collection.createIndex("bloodGroup", IndexOptions.indexOptions(IndexType.NonUnique)); - db.close(); - - Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { - @Override - public void migrate(Instruction instruction) { - instruction.forDatabase() - .addPassword("test-user", "test-password"); - - instruction.forCollection("test") - .rename("testCollectionMigrate") - .deleteField("lastName"); - } - }; - - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate("test-user", "test-password"); - - collection = db.getCollection("testCollectionMigrate"); - assertTrue(collection.hasIndex("firstName")); - assertEquals(collection.size(), 10); - assertEquals(db.listCollectionNames().size(), 1); - assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 2); - db.close(); - - migration = new Migration(2, 3) { - @Override - public void migrate(Instruction instruction) { - instruction.forDatabase() - .changePassword("test-user", "test-password", "password"); - - instruction.forCollection("testCollectionMigrate") - .dropIndex("firstName") - .deleteField("bloodGroup") - .addField("name", document -> faker.name().fullName()) - .addField("address") - .addField("vehicles", 1) - .renameField("age", "ageGroup") - .createIndex("ageGroup", IndexType.NonUnique); - } - }; - - storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(3) - .addMigrations(migration) - .openOrCreate("test-user", "password"); - - collection = db.getCollection("testCollectionMigrate"); - assertEquals(collection.size(), 10); - assertEquals(db.listCollectionNames().size(), 1); - assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 3); - - assertFalse(collection.hasIndex("firstName")); - assertTrue(collection.hasIndex("ageGroup")); - assertEquals(collection.find(where("age").notEq(null)).size(), 0); - } - - @Test(expected = MigrationException.class) - public void testOpenWithoutSchemaVersion() { - NitriteCollection collection = db.getCollection("test"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("test") - .rename("testOpenWithoutSchemaVersion") - .deleteField("lastName"); - } - }; - - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testOpenWithoutSchemaVersion"); - assertEquals(collection.size(), 10); - db.close(); - - storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(); - - collection = db.getCollection("testOpenWithoutSchemaVersion"); - assertEquals(collection.size(), 10); - } - - @Test - public void testDescendingSchema() { - NitriteCollection collection = db.getCollection("test"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("test") - .rename("testDescendingSchema") - .deleteField("lastName"); - } - }; - - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testDescendingSchema"); - assertEquals(collection.size(), 10); - db.close(); - - migration = new Migration(2, Constants.INITIAL_SCHEMA_VERSION) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("testDescendingSchema") - .rename("test"); - } - }; - - storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(1) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - } - - @Test - public void testMigrationWithoutVersion() { - NitriteCollection collection = db.getCollection("test"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("test") - .rename("testMigrationWithoutVersion") - .deleteField("lastName"); - } - }; - - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testMigrationWithoutVersion"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - } - - @Test - public void testWrongSchemaVersionNoMigration() { - NitriteCollection collection = db.getCollection("testWrongSchemaVersionNoMigration"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration = new Migration(1, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("testWrongSchemaVersionNoMigration") - .rename("test") - .deleteField("lastName"); - } - }; - - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testWrongSchemaVersionNoMigration"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - - migration = new Migration(2, 3) { - @Override - public void migrate(Instruction instruction) { - instruction.forCollection("test") - .rename("testWrongSchemaVersionNoMigration"); - } - }; - - storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testWrongSchemaVersionNoMigration"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - } - - @Test - public void testReOpenAfterMigration() { - NitriteCollection collection = db.getCollection("testReOpenAfterMigration"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration = new Migration(1, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("testReOpenAfterMigration") - .rename("test") - .deleteField("lastName"); - } - }; - - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testReOpenAfterMigration"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testReOpenAfterMigration"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .openOrCreate(); - - collection = db.getCollection("testReOpenAfterMigration"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - } - - @Test - public void testMultipleMigrations() { - NitriteCollection collection = db.getCollection("testMultipleMigrations"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration1 = new Migration(1, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("testMultipleMigrations") - .rename("test"); - } - }; - - Migration migration2 = new Migration(2, 3) { - @Override - public void migrate(Instruction instruction) { - instruction.forCollection("test") - .addField("fullName", "Dummy Name"); - } - }; - - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration1, migration2) - .openOrCreate(); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - assertEquals(collection.find(where("fullName").eq("Dummy Name")).size(), 0); - db.close(); - - Migration migration3 = new Migration(3, 4) { - @Override - public void migrate(Instruction instruction) { - instruction.forCollection("test") - .addField("age", 10); - } - }; - - storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(4) - .addMigrations(migration1, migration2, migration3) - .openOrCreate(); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - assertEquals(collection.find(where("fullName").eq("Dummy Name")).size(), 10); - assertEquals(collection.find(where("age").eq(10)).size(), 10); - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/migrate/NewClass.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/migrate/NewClass.java deleted file mode 100644 index 401cbbf77..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/migrate/NewClass.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.dizitart.no2.test.migrate; - -import lombok.Data; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.repository.annotations.Entity; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; - -/** - * @author Anindya Chatterjee - */ -@Data -@Entity(value = "new", indices = { - @Index(value = "familyName", type = IndexType.NonUnique), - @Index(value = "fullName", type = IndexType.NonUnique), - @Index(value = "literature.ratings", type = IndexType.NonUnique), -}) -public class NewClass { - @Id - private Long empId; - private String firstName; - private String familyName; - private String fullName; - private Literature literature; - - - @Data - public static class Literature { - private String text; - private Integer ratings; - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/migrate/OldClass.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/migrate/OldClass.java deleted file mode 100644 index 5f462da3c..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/migrate/OldClass.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.dizitart.no2.test.migrate; - -import lombok.Data; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.repository.annotations.Entity; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; - -/** - * @author Anindya Chatterjee - */ -@Data -@Entity(value = "old", indices = { - @Index(value = "firstName", type = IndexType.NonUnique), - @Index(value = "lastName", type = IndexType.NonUnique), - @Index(value = "literature.text", type = IndexType.Fulltext), - @Index(value = "literature.ratings", type = IndexType.NonUnique), -}) -public class OldClass { - @Id - private String uuid; - private String empId; - private String firstName; - private String lastName; - private Literature literature; - - - @Data - public static class Literature { - private String text; - private Float ratings; - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/transaction/TransactionRepositoryTest.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/transaction/TransactionRepositoryTest.java deleted file mode 100644 index 87a92087a..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/transaction/TransactionRepositoryTest.java +++ /dev/null @@ -1,810 +0,0 @@ -package org.dizitart.no2.test.transaction; - -import com.github.javafaker.Faker; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.TransactionException; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.test.BaseObjectRepositoryTest; -import org.dizitart.no2.test.data.SubEmployee; -import org.dizitart.no2.transaction.Session; -import org.dizitart.no2.transaction.Transaction; -import org.junit.Test; - -import java.util.*; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -public class TransactionRepositoryTest extends BaseObjectRepositoryTest { - - @Test - public void testCommitInsert() { - ObjectRepository repository = db.getRepository(TxData.class); - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - TxData txData1 = new TxData(); - txData1.setId(1L); - txData1.setName("John"); - - txRepo.insert(txData1); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 1); - assertNotEquals(repository.find(where("name").eq("John")).size(), 1); - - transaction.commit(); - - assertEquals(repository.find(where("name").eq("John")).size(), 1); - } - } - } - - @Test - public void testRollbackInsert() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - TxData txData1 = new TxData(); - txData1.setId(1L); - txData1.setName("John"); - - TxData txData2 = new TxData(); - txData2.setId(2L); - txData2.setName("Jane"); - - txRepo.insert(txData1, txData2); - - txData2.setName("Molly"); - repository.insert(txData2); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 1); - assertEquals(repository.find(where("name").eq("John")).size(), 0); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(repository.find(where("name").eq("John")).size(), 0); - assertEquals(repository.find(where("name").eq("Molly")).size(), 1); - } - } - } - - @Test - public void testCommitUpdate() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(new TxData(1L, "John")); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - TxData txData1 = new TxData(1L, "Jane"); - txRepo.update(txData1, true); - - assertEquals(txRepo.find(where("name").eq("Jane")).size(), 1); - assertNotEquals(repository.find(where("name").eq("Jane")).size(), 1); - - transaction.commit(); - - assertEquals(repository.find(where("name").eq("Jane")).size(), 1); - } - } - } - - @Test - public void testRollbackUpdate() { - ObjectRepository repository = db.getRepository(TxData.class, "rollback"); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(new TxData(1L, "Jane")); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - ObjectRepository txRepo = transaction.getRepository(TxData.class, "rollback"); - - TxData txData1 = new TxData(); - txData1.setId(2L); - txData1.setName("John"); - - TxData txData2 = new TxData(); - txData2.setId(1L); - txData2.setName("Jane Doe"); - txRepo.update(txData2); - txRepo.insert(txData1); - - // just to create UniqueConstraintViolation for rollback - repository.insert(txData1); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 1); - assertEquals(txRepo.find(where("name").eq("Jane Doe")).size(), 1); - assertNotEquals(repository.find(where("name").eq("Jane Doe")).size(), 1); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(repository.find(where("name").eq("Jane")).size(), 1); - assertNotEquals(repository.find(where("name").eq("Jane Doe")).size(), 1); - } - } - } - - @Test - public void testCommitRemove() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - txRepo.remove(where("name").eq("John")); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 0); - assertEquals(repository.find(where("name").eq("John")).size(), 1); - - transaction.commit(); - - assertEquals(repository.find(where("name").eq("John")).size(), 0); - } - } - } - - @Test - public void testRollbackRemove() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - TxData txData1 = new TxData(1L, "John"); - repository.insert(txData1); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - txRepo.remove(where("name").eq("John")); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 0); - assertEquals(repository.find(where("name").eq("John")).size(), 1); - - TxData txData2 = new TxData(2L, "Jane"); - txRepo.insert(txData2); - repository.insert(txData2); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(repository.find(where("name").eq("John")).size(), 1); - assertEquals(repository.find(where("name").eq("Jane")).size(), 1); - } - } - } - - @Test - public void testCommitCreateIndex() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.createIndex("name", indexOptions(IndexType.Fulltext)); - - assertTrue(txRepo.hasIndex("name")); - assertFalse(repository.hasIndex("name")); - - transaction.commit(); - - assertTrue(repository.hasIndex("name")); - } - } - } - - @Test - public void testRollbackCreateIndex() { - TxData txData1 = new TxData(1L, "John"); - TxData txData2 = new TxData(2L, "Jane"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.createIndex("name", indexOptions(IndexType.Fulltext)); - - assertTrue(txRepo.hasIndex("name")); - assertFalse(repository.hasIndex("name")); - - txRepo.insert(txData2); - repository.insert(txData2); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertFalse(repository.hasIndex("name")); - } - } - } - - @Test - public void testCommitClear() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.clear(); - - assertEquals(0, txRepo.size()); - assertEquals(1, repository.size()); - - transaction.commit(); - - assertEquals(0, repository.size()); - } - } - } - - @Test - public void testRollbackClear() { - TxData txData1 = new TxData(1L, "John"); - TxData txData2 = new TxData(2L, "Jane"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.clear(); - - assertEquals(0, txRepo.size()); - assertEquals(1, repository.size()); - - txRepo.insert(txData2); - repository.insert(txData2); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(2, repository.size()); - } - } - } - - @Test - public void testCommitDropIndex() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.dropIndex("name"); - - assertFalse(txRepo.hasIndex("name")); - assertTrue(repository.hasIndex("name")); - - transaction.commit(); - - assertFalse(repository.hasIndex("name")); - } - } - } - - @Test - public void testRollbackDropIndex() { - TxData txData1 = new TxData(1L, "John"); - TxData txData2 = new TxData(2L, "Jane"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.dropIndex("name"); - - assertFalse(txRepo.hasIndex("name")); - assertTrue(repository.hasIndex("name")); - - txRepo.insert(txData2); - repository.insert(txData2); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertTrue(repository.hasIndex("name")); - } - } - } - - @Test - public void testCommitDropAllIndices() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.dropAllIndices(); - - assertFalse(txRepo.hasIndex("name")); - assertTrue(repository.hasIndex("name")); - - transaction.commit(); - - assertFalse(repository.hasIndex("name")); - } - } - } - - @Test - public void testRollbackDropAllIndices() { - TxData txData1 = new TxData(1L, "John"); - TxData txData2 = new TxData(2L, "Jane"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.dropAllIndices(); - - assertFalse(txRepo.hasIndex("name")); - assertTrue(repository.hasIndex("name")); - - txRepo.insert(txData2); - repository.insert(txData2); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertTrue(repository.hasIndex("name")); - } - } - } - - @Test - public void testCommitDropRepository() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.drop(); - - boolean expectedException = false; - try { - assertEquals(0, txRepo.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - assertEquals(1, repository.size()); - - transaction.commit(); - - expectedException = false; - try { - assertEquals(0, repository.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - } - } - } - - @Test - public void testRollbackDropRepository() { - TxData txData1 = new TxData(1L, "John"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.drop(); - - boolean expectedException = false; - try { - assertEquals(0, txRepo.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - assertEquals(1, repository.size()); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(1, repository.size()); - } - } - } - - @Test - public void testCommitSetAttribute() { - ObjectRepository repository = db.getRepository(TxData.class); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - Attributes attributes = new Attributes(); - attributes.setAttributes(Collections.singletonMap("key", "value")); - txRepo.setAttributes(attributes); - - assertNull(repository.getAttributes()); - - transaction.commit(); - - assertEquals("value", repository.getAttributes().get("key")); - } - } - } - - @Test - public void testRollbackSetAttribute() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - Attributes attributes = new Attributes(); - Map map = new HashMap<>(); - map.put("key", "value"); - attributes.setAttributes(map); - txRepo.setAttributes(attributes); - - txRepo.insert(new TxData(1L, "John")); - txRepo.insert(new TxData(2L, "Jane")); - - assertNull(repository.getAttributes()); - - // just to create UniqueConstraintViolation for rollback - repository.insert(new TxData(2L, "Jane")); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 1); - assertNotEquals(repository.find(where("name").eq("John")).size(), 1); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertNull(repository.getAttributes().get("key")); - } - } - } - - @Test - public void testConcurrentInsertAndRemove() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.NonUnique)); - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - final long fi = i; - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - for (long j = 0; j < 10; j++) { - TxData txData = new TxData(j + (fi * 10), faker.name().name()); - txRepo.insert(txData); - } - - txRepo.remove(where("id").eq(2L + (fi * 10))); - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(90, repository.size()); - } - } - - @Test - public void testConcurrentInsert() { - ObjectRepository repository = db.getRepository(TxData.class); - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - final long fi = i; - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - for (long j = 0; j < 10; j++) { - TxData txData = new TxData(j + (fi * 10), faker.name().name()); - txRepo.insert(txData); - } - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(100, repository.size()); - } - } - - @Test - public void testConcurrentUpdate() { - ObjectRepository repository = db.getRepository(TxData.class); - Faker faker = new Faker(); - for (long j = 0; j < 10; j++) { - TxData txData = new TxData(j, faker.name().name()); - repository.insert(txData); - } - - List> futures = new ArrayList<>(); - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - for (int j = 0; j < 10; j++) { - TxData txData = new TxData((long) j, faker.name().name()); - txRepo.update(where("id").eq(j), txData); - } - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(10, repository.size()); - } - } - - @Test - public void testTransactionOnDifferentRepositoriesAndCollections() { - ObjectRepository repo1 = db.getRepository(TxData.class); - ObjectRepository repo2 = db.getRepository(TxData.class, "2"); - ObjectRepository repo3 = db.getRepository(SubEmployee.class); - NitriteCollection col1 = db.getCollection("test1"); - col1.createIndex("id", indexOptions(IndexType.Unique)); - - Faker faker = new Faker(); - - try(Session session = db.createSession()) { - Transaction transaction = session.beginTransaction(); - - ObjectRepository txRepo1 = transaction.getRepository(TxData.class); - ObjectRepository txRepo2 = transaction.getRepository(TxData.class, "2"); - ObjectRepository txRepo3 = transaction.getRepository(SubEmployee.class); - NitriteCollection test1 = transaction.getCollection("test1"); - - for (long i = 0; i < 10; i++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", i); - test1.insert(document); - - TxData txData1 = new TxData(i, faker.name().name()); - txRepo1.insert(txData1); - - TxData txData2 = new TxData(i + 10, faker.name().name()); - txRepo2.insert(txData2); - - SubEmployee employee = new SubEmployee(); - employee.setAddress(faker.address().fullAddress()); - employee.setEmpId(i); - employee.setJoinDate(faker.date().birthday()); - txRepo3.insert(employee); - } - - assertEquals(test1.size(), 10); - assertEquals(txRepo1.size(), 10); - assertEquals(txRepo2.size(), 10); - assertEquals(txRepo3.size(), 10); - - assertEquals(col1.size(), 0); - assertEquals(repo1.size(), 0); - assertEquals(repo2.size(), 0); - assertEquals(repo3.size(), 0); - - transaction.commit(); - - assertEquals(col1.size(), 10); - assertEquals(repo1.size(), 10); - assertEquals(repo2.size(), 10); - assertEquals(repo3.size(), 10); - } - - Transaction transaction = null; - try (Session session = db.createSession()) { - transaction = session.beginTransaction(); - - ObjectRepository txRepo1 = transaction.getRepository(TxData.class); - ObjectRepository txRepo2 = transaction.getRepository(TxData.class, "2"); - ObjectRepository txRepo3 = transaction.getRepository(SubEmployee.class); - NitriteCollection test1 = transaction.getCollection("test1"); - - for (long i = 0; i < 10; i++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 10); - test1.insert(document); - - TxData txData1 = new TxData(i + 10, faker.name().name()); - txRepo1.insert(txData1); - - TxData txData2 = new TxData(i + 20, faker.name().name()); - txRepo2.insert(txData2); - - SubEmployee employee = new SubEmployee(); - employee.setAddress(faker.address().fullAddress()); - employee.setEmpId(i + 10); - employee.setJoinDate(faker.date().birthday()); - txRepo3.insert(employee); - } - - assertEquals(test1.size(), 20); - assertEquals(txRepo1.size(), 20); - assertEquals(txRepo2.size(), 20); - assertEquals(txRepo3.size(), 20); - - assertEquals(col1.size(), 10); - assertEquals(repo1.size(), 10); - assertEquals(repo2.size(), 10); - assertEquals(repo3.size(), 10); - - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", 12L); - col1.insert(document); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - - assertEquals(col1.size(), 11); // last doc added - assertEquals(repo1.size(), 10); - assertEquals(repo2.size(), 10); - assertEquals(repo3.size(), 10); - } - } - - @Test(expected = TransactionException.class) - public void testFailureOnClosedTransaction() { - try(Session session = db.createSession()) { - Transaction transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.insert(new TxData(1L, "John")); - transaction.commit(); - - txRepo.insert(new TxData(2L, "Jane")); - fail(); - } - } -} diff --git a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/transaction/TxData.java b/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/transaction/TxData.java deleted file mode 100644 index 12899009e..000000000 --- a/nitrite-jackson-mapper/src/test/java/org/dizitart/no2/test/transaction/TxData.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.test.transaction; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -class TxData { - @Id - private Long id; - private String name; -} diff --git a/nitrite-mapdb-adapter/build.gradle b/nitrite-mapdb-adapter/build.gradle deleted file mode 100644 index 9b80a4f98..000000000 --- a/nitrite-mapdb-adapter/build.gradle +++ /dev/null @@ -1,132 +0,0 @@ -plugins { - id 'java-library' - id 'signing' - id 'maven-publish' - id 'com.github.hauner.jarTest' - id 'jacoco' -} - -jar { - archivesBaseName = 'nitrite-mapdb-adapter' -} - -java { - withJavadocJar() - withSourcesJar() - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 -} - -compileJava.options.encoding = 'UTF-8' -compileTestJava.options.encoding = 'UTF-8' -javadoc.options.encoding = 'UTF-8' - -repositories { - mavenCentral() -} - -dependencies { - api platform(project(':nitrite-bom')) - api project(':nitrite') - api "org.slf4j:slf4j-api" - api "org.mapdb:mapdb" - - annotationProcessor "org.projectlombok:lombok:1.18.14" - - testAnnotationProcessor "org.projectlombok:lombok:1.18.12" - testImplementation "uk.co.jemos.podam:podam:7.2.5.RELEASE" - testImplementation "com.github.javafaker:javafaker:1.0.2" - testImplementation "junit:junit:4.13.1" - testImplementation "org.apache.lucene:lucene-core:8.6.3" - testImplementation "org.apache.lucene:lucene-analyzers-common:8.6.3" - testImplementation "org.apache.lucene:lucene-queryparser:8.6.3" - testImplementation "org.apache.logging.log4j:log4j-slf4j-impl:2.13.3" - testImplementation "org.apache.logging.log4j:log4j-core:2.13.3" - testImplementation "org.awaitility:awaitility:4.0.3" - testImplementation "joda-time:joda-time:2.10.6" - testImplementation "org.meanbean:meanbean:2.0.3" - testImplementation "com.fasterxml.jackson.core:jackson-databind:2.11.3" - testImplementation "commons-io:commons-io:2.8.0" -} - -test { - testLogging.showStandardStreams = false - testLogging.exceptionFormat = 'full' -} - -jacocoTestReport { - reports { - xml.enabled true - xml.destination file("${buildDir}/reports/jacoco/report.xml") - csv.enabled false - html.destination file("${buildDir}/reports/coverage") - } -} - -check.dependsOn jacocoTestReport - -publishing { - publications { - mavenJava(MavenPublication) { - artifactId = 'nitrite-mapdb-adapter' - from components.java - versionMapping { - usage('java-api') { - fromResolutionOf('runtimeClasspath') - } - usage('java-runtime') { - fromResolutionResult() - } - } - pom { - name = 'Nitrite MapDB Storage Engine' - description = 'An in-memory, file-based embedded nosql persistent document store based on mapdb.' - url = 'https://github.com/nitrite/nitrite-java' - licenses { - license { - name = 'The Apache License, Version 2.0' - url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' - } - } - developers { - developer { - id = 'anidotnet' - name = 'Anindya Chatterjee' - email = 'anidotnet@gmail.com' - } - } - scm { - connection = 'scm:git:git@github.com:nitrite/nitrite-java.git' - developerConnection = 'scm:git:git@github.com:nitrite/nitrite-java.git' - url = 'git@github.com:nitrite/nitrite-java.git' - } - } - } - } - repositories { - if (version.endsWith('SNAPSHOT') || project.hasProperty('release')) { - maven { - name = "OSSRH" - def releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/" - def snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots" - url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl - credentials { - username System.getenv('MAVEN_USERNAME') - password System.getenv('MAVEN_PASSWORD') - } - - } - } - } -} - -signing { - sign publishing.publications.mavenJava -} - - -javadoc { - if(JavaVersion.current().isJava9Compatible()) { - options.addBooleanOption('html5', true) - } -} \ No newline at end of file diff --git a/nitrite-mapdb-adapter/lombok.config b/nitrite-mapdb-adapter/lombok.config deleted file mode 100644 index 189c0bef9..000000000 --- a/nitrite-mapdb-adapter/lombok.config +++ /dev/null @@ -1,3 +0,0 @@ -# This file is generated by the 'io.freefair.lombok' Gradle plugin -config.stopBubbling = true -lombok.addLombokGeneratedAnnotation = true diff --git a/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/MapDBConfig.java b/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/MapDBConfig.java deleted file mode 100644 index 4c698d4c9..000000000 --- a/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/MapDBConfig.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.dizitart.no2.mapdb; - -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; -import org.dizitart.no2.store.StoreConfig; -import org.dizitart.no2.store.events.StoreEventListener; -import org.mapdb.serializer.GroupSerializer; -import org.mapdb.volume.Volume; - -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * @author Anindya Chatterjee - */ -@Accessors(fluent = true) -public class MapDBConfig implements StoreConfig { - @Getter - @Setter(AccessLevel.PACKAGE) - private Set eventListeners; - - @Getter @Setter(AccessLevel.PACKAGE) - private String filePath = null; - - @Getter @Setter(AccessLevel.PACKAGE) - private MapDBStoreType storeType = null; - - @Getter @Setter(AccessLevel.PACKAGE) - private Volume volume = null; - - @Getter @Setter(AccessLevel.PACKAGE) - private Boolean volumeExists = null; - - @Getter @Setter(AccessLevel.PACKAGE) - private Long allocateStartSize = null; - - @Getter @Setter(AccessLevel.PACKAGE) - private Long allocateIncrement = null; - - @Getter @Setter(AccessLevel.PACKAGE) - private Boolean fileDeleteAfterClose = null; - - @Getter @Setter(AccessLevel.PACKAGE) - private Boolean fileDeleteAfterOpen = null; - - @Getter @Setter(AccessLevel.PACKAGE) - private Boolean isThreadSafe = null; - - @Getter @Setter(AccessLevel.PACKAGE) - private Integer concurrencyScale = null; - - @Getter @Setter(AccessLevel.PACKAGE) - private Boolean cleanerHack = null; - - @Getter @Setter(AccessLevel.PACKAGE) - private Boolean fileMmapPreclearDisable = null; - - @Getter @Setter(AccessLevel.PACKAGE) - private Long fileLockWait = null; - - @Getter @Setter(AccessLevel.PACKAGE) - private Boolean fileMmapfIfSupported = null; - - @Getter @Setter(AccessLevel.PACKAGE) - private Boolean closeOnJvmShutdown = null; - - @Getter @Setter(AccessLevel.PACKAGE) - private Boolean closeOnJvmShutdownWeakReference = null; - - @Getter @Setter(AccessLevel.PACKAGE) - private Boolean isReadOnly = false; - - @Getter @Setter(AccessLevel.PACKAGE) - private Boolean checksumStoreEnable = null; - - @Getter @Setter(AccessLevel.PACKAGE) - private Boolean checksumHeaderBypass = null; - - @Getter @Setter(AccessLevel.PACKAGE) - private Map, GroupSerializer> serializerRegistry = null; - - MapDBConfig() { - eventListeners = new HashSet<>(); - } - - @Override - public void addStoreEventListener(StoreEventListener listener) { - eventListeners.add(listener); - } -} diff --git a/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/MapDBMap.java b/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/MapDBMap.java deleted file mode 100644 index 7eabe6740..000000000 --- a/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/MapDBMap.java +++ /dev/null @@ -1,243 +0,0 @@ -package org.dizitart.no2.mapdb; - -import lombok.AccessLevel; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import org.dizitart.no2.common.NullEntry; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.store.NitriteMap; -import org.dizitart.no2.store.NitriteStore; -import org.mapdb.BTreeMap; -import org.mapdb.DBException; - -import java.util.Iterator; -import java.util.Map; - -import static org.dizitart.no2.common.util.ValidationUtils.notNull; - -/** - * @author Anindya Chatterjee - */ -@Slf4j -public class MapDBMap implements NitriteMap { - @Getter(AccessLevel.PACKAGE) - private final BTreeMap bTreeMap; - - @Getter(AccessLevel.PACKAGE) - private final BTreeMap nullEntryMap; - - private final NitriteStore nitriteStore; - private final String mapName; - - - public MapDBMap(String mapName, BTreeMap bTreeMap, - BTreeMap nullEntryMap, NitriteStore nitriteStore) { - this.bTreeMap = bTreeMap; - this.mapName = mapName; - this.nitriteStore = nitriteStore; - this.nullEntryMap = nullEntryMap; - } - - @Override - public boolean containsKey(K k) { - if (k == null) { - return nullEntryMap.containsKey(NullEntry.getInstance()); - } - return bTreeMap.containsKey(k); - } - - @Override - public V get(K k) { - if (k == null) { - return nullEntryMap.get(NullEntry.getInstance()); - } - - Map.Entry firstEntry = bTreeMap.firstEntry(); - if (firstEntry != null) { - K firstKey = firstEntry.getKey(); - if (firstKey.getClass().equals(k.getClass())) { - return bTreeMap.get(k); - } - } - return null; - } - - @Override - public NitriteStore getStore() { - return nitriteStore; - } - - @Override - public void clear() { - bTreeMap.clear(); - nullEntryMap.clear(); - updateLastModifiedTime(); - } - - @Override - public String getName() { - return mapName; - } - - @Override - public RecordStream values() { - return RecordStream.fromCombined(bTreeMap.values(), nullEntryMap.values()); - } - - @Override - public V remove(K k) { - V value; - if (k == null) { - value = nullEntryMap.remove(NullEntry.getInstance()); - } else { - value = bTreeMap.remove(k); - } - updateLastModifiedTime(); - return value; - } - - @Override - public RecordStream keySet() { - return RecordStream.fromIterable(() -> new Iterator() { - final Iterator keyIterator = bTreeMap.keyIterator(); - final Iterator nullEntryIterator = nullEntryMap.keyIterator(); - - @Override - public boolean hasNext() { - boolean result = nullEntryIterator.hasNext(); - if (!result) { - return keyIterator.hasNext(); - } - return true; - } - - @Override - public K next() { - if (nullEntryIterator.hasNext()) { - return null; - } else { - return keyIterator.next(); - } - } - }); - } - - @Override - public void put(K k, V v) { - notNull(v, "value cannot be null"); - try { - if (k == null) { - nullEntryMap.put(NullEntry.getInstance(), v); - } else { - Map.Entry firstEntry = bTreeMap.firstEntry(); - if (firstEntry != null) { - if (!firstEntry.getKey().getClass().equals(k.getClass())) { - return; - } - } - bTreeMap.put(k, v); - } - updateLastModifiedTime(); - } catch (DBException e) { - log.error("Error while writing data", e); - throw new NitriteIOException("failed to write data", e); - } - } - - @Override - public long size() { - return bTreeMap.sizeLong() + nullEntryMap.sizeLong(); - } - - @Override - public V putIfAbsent(K k, V v) { - notNull(v, "value cannot be null"); - - V value; - if (k == null) { - value = nullEntryMap.putIfAbsent(NullEntry.getInstance(), v); - } else { - value = bTreeMap.putIfAbsent(k, v); - } - updateLastModifiedTime(); - return value; - } - - @Override - public RecordStream> entries() { - return () -> new Iterator>() { - final Iterator> entryIterator = bTreeMap.entrySet().iterator(); - final Iterator> nullEntryIterator = nullEntryMap.entrySet().iterator(); - - @Override - public boolean hasNext() { - boolean result = nullEntryIterator.hasNext(); - if (!result) { - return entryIterator.hasNext(); - } - return true; - } - - @Override - public Pair next() { - if (nullEntryIterator.hasNext()) { - Map.Entry entry = nullEntryIterator.next(); - return new Pair<>(null, entry.getValue()); - } else { - Map.Entry entry = entryIterator.next(); - return new Pair<>(entry.getKey(), entry.getValue()); - } - } - }; - } - - @Override - public K higherKey(K k) { - if (k == null) { - return null; - } - return bTreeMap.higherKey(k); - } - - @Override - public K ceilingKey(K k) { - if (k == null) { - return null; - } - return bTreeMap.ceilingKey(k); - } - - @Override - public K lowerKey(K k) { - if (k == null) { - return null; - } - return bTreeMap.lowerKey(k); - } - - @Override - public K floorKey(K k) { - if (k == null) { - return null; - } - return bTreeMap.floorKey(k); - } - - @Override - public boolean isEmpty() { - return bTreeMap.isEmpty() && nullEntryMap.isEmpty(); - } - - @Override - public void drop() { - nitriteStore.removeMap(getName()); - } - - @Override - public void close() { - bTreeMap.close(); - nullEntryMap.close(); - } -} diff --git a/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/MapDBModule.java b/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/MapDBModule.java deleted file mode 100644 index d3a16198d..000000000 --- a/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/MapDBModule.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.dizitart.no2.mapdb; - -import lombok.AccessLevel; -import lombok.Setter; -import org.dizitart.no2.module.NitritePlugin; -import org.dizitart.no2.store.NitriteStore; -import org.dizitart.no2.store.StoreModule; - -import java.util.Set; - -/** - * @author Anindya Chatterjee - */ -public class MapDBModule implements StoreModule { - - @Setter(AccessLevel.PACKAGE) - private MapDBConfig storeConfig; - - public MapDBModule(String path) { - this.storeConfig = new MapDBConfig(); - this.storeConfig.filePath(path); - } - - public static MapDBModuleBuilder withConfig() { - return new MapDBModuleBuilder(); - } - - @Override - public NitriteStore getStore() { - MapDBStore store = new MapDBStore(); - store.setStoreConfig(storeConfig); - return store; - } - - @Override - public Set plugins() { - return setOf(getStore()); - } -} diff --git a/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/MapDBModuleBuilder.java b/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/MapDBModuleBuilder.java deleted file mode 100644 index ba4e2ead2..000000000 --- a/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/MapDBModuleBuilder.java +++ /dev/null @@ -1,107 +0,0 @@ -package org.dizitart.no2.mapdb; - -import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; -import org.dizitart.no2.store.events.StoreEventListener; -import org.mapdb.serializer.GroupSerializer; -import org.mapdb.volume.Volume; - -import java.io.File; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@Accessors(fluent = true) -public class MapDBModuleBuilder { - private String filePath; - private MapDBStoreType storeType = null; - private Volume volume = null; - private Boolean volumeExists = null; - private Long allocateStartSize = null; - private Long allocateIncrement = null; - private Boolean fileDeleteAfterClose = null; - private Boolean fileDeleteAfterOpen = null; - private Boolean isThreadSafe = null; - private Integer concurrencyScale = null; - private Boolean cleanerHack = null; - private Boolean fileMmapPreclearDisable = null; - private Long fileLockWait = null; - private Boolean fileMmapfIfSupported = null; - private Boolean closeOnJvmShutdown = null; - private Boolean closeOnJvmShutdownWeakReference = null; - private Boolean readOnly = false; - private Boolean checksumStoreEnable = null; - private Boolean checksumHeaderBypass = null; - - private MapDBConfig dbConfig; - - @Setter(AccessLevel.NONE) - private final Set eventListeners; - - @Setter(AccessLevel.NONE) - private final Map, GroupSerializer> serializerRegistry; - - MapDBModuleBuilder() { - dbConfig = new MapDBConfig(); - eventListeners = new HashSet<>(); - serializerRegistry = new HashMap<>(); - } - - public MapDBModuleBuilder filePath(File file) { - if (file != null) { - this.filePath = file.getPath(); - } - return this; - } - - public MapDBModuleBuilder filePath(String path) { - this.filePath = path; - return this; - } - - public MapDBModuleBuilder addStoreEventListener(StoreEventListener listener) { - eventListeners.add(listener); - return this; - } - - public void registerSerializer(Class type, GroupSerializer serializer) { - serializerRegistry.put(type, serializer); - } - - public MapDBModule build() { - MapDBModule module = new MapDBModule(filePath()); - - dbConfig.filePath(filePath()); - dbConfig.storeType(storeType()); - dbConfig.volume(volume()); - dbConfig.volumeExists(volumeExists()); - dbConfig.allocateStartSize(allocateStartSize()); - dbConfig.allocateIncrement(allocateIncrement()); - dbConfig.fileDeleteAfterClose(fileDeleteAfterClose()); - dbConfig.fileDeleteAfterOpen(fileDeleteAfterOpen()); - dbConfig.isThreadSafe(isThreadSafe()); - dbConfig.concurrencyScale(concurrencyScale()); - dbConfig.cleanerHack(cleanerHack()); - dbConfig.fileMmapPreclearDisable(fileMmapPreclearDisable()); - dbConfig.fileLockWait(fileLockWait()); - dbConfig.fileMmapfIfSupported(fileMmapfIfSupported()); - dbConfig.closeOnJvmShutdown(closeOnJvmShutdown()); - dbConfig.closeOnJvmShutdownWeakReference(closeOnJvmShutdownWeakReference()); - dbConfig.isReadOnly(readOnly()); - dbConfig.checksumStoreEnable(checksumStoreEnable()); - dbConfig.checksumHeaderBypass(checksumHeaderBypass()); - dbConfig.serializerRegistry(serializerRegistry()); - dbConfig.eventListeners(eventListeners()); - - module.setStoreConfig(dbConfig); - return module; - } -} diff --git a/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/MapDBStore.java b/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/MapDBStore.java deleted file mode 100644 index 22ba080d2..000000000 --- a/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/MapDBStore.java +++ /dev/null @@ -1,153 +0,0 @@ -package org.dizitart.no2.mapdb; - -import lombok.extern.slf4j.Slf4j; -import org.dizitart.no2.common.NullEntry; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.index.BoundingBox; -import org.dizitart.no2.mapdb.serializers.Serializers; -import org.dizitart.no2.store.AbstractNitriteStore; -import org.dizitart.no2.store.NitriteMap; -import org.dizitart.no2.store.NitriteRTree; -import org.dizitart.no2.store.events.StoreEventListener; -import org.dizitart.no2.store.events.StoreEvents; -import org.mapdb.BTreeMap; -import org.mapdb.DB; -import org.mapdb.serializer.GroupSerializer; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * @author Anindya Chatterjee - */ -@Slf4j -public class MapDBStore extends AbstractNitriteStore { - private DB db; - private final Map> nitriteMapRegistry; - - public MapDBStore() { - super(); - nitriteMapRegistry = new ConcurrentHashMap<>(); - } - - @Override - public void openOrCreate() { - this.db = StoreFactory.open(getStoreConfig()); - initEventBus(); - alert(StoreEvents.Opened); - } - - @Override - public boolean isClosed() { - return db == null || db.isClosed(); - } - - @Override - public boolean hasUnsavedChanges() { - return false; - } - - @Override - public boolean isReadOnly() { - return db.getStore().isReadOnly(); - } - - @Override - public void commit() { - db.commit(); - alert(StoreEvents.Commit); - } - - @Override - public void close() { - db.close(); - alert(StoreEvents.Closed); - } - - @Override - public boolean hasMap(String mapName) { - return db.exists(mapName); - } - - @Override - @SuppressWarnings("unchecked") - public NitriteMap openMap(String mapName, Class keyType, Class valueType) { - if (nitriteMapRegistry.containsKey(mapName)) { - return (MapDBMap) nitriteMapRegistry.get(mapName); - } - - GroupSerializer keySerializer = Serializers.findSerializer(keyType); - GroupSerializer valueSerializer = Serializers.findSerializer(valueType); - - DB.TreeMapMaker treeMapMaker = (DB.TreeMapMaker) db.treeMap(mapName) - .counterEnable() - .valuesOutsideNodesEnable(); - - if (keySerializer != null) { - treeMapMaker.keySerializer(keySerializer); - } - - if (valueSerializer != null) { - treeMapMaker.valueSerializer(valueSerializer); - } - - BTreeMap bTreeMap = treeMapMaker.createOrOpen(); - - // mapdb btreemap does not support null key, so all null key entries are maintained in a separate map - DB.TreeMapMaker nullMapMaker = (DB.TreeMapMaker) db - .treeMap(mapName + "null-map") - .counterEnable() - .valuesOutsideNodesEnable(); - - if (valueSerializer != null) { - nullMapMaker.valueSerializer(valueSerializer); - } - - BTreeMap nullMap = nullMapMaker.createOrOpen(); - - MapDBMap mapDBMap = new MapDBMap<>(mapName, bTreeMap, nullMap, this); - nitriteMapRegistry.put(mapName, mapDBMap); - return mapDBMap; - } - - @Override - public void removeMap(String mapName) { - if (nitriteMapRegistry.containsKey(mapName)) { - MapDBMap mapDb = (MapDBMap) nitriteMapRegistry.get(mapName); - BTreeMap bTreeMap = mapDb.getBTreeMap(); - BTreeMap nullEntryMap = mapDb.getNullEntryMap(); - - bTreeMap.clear(); - nullEntryMap.clear(); - - nitriteMapRegistry.remove(mapName); - } - } - - @Override - public NitriteRTree openRTree(String rTreeName, Class keyType, Class valueType) { - throw new InvalidOperationException("rtree not supported on mapdb store"); - } - - @Override - public void removeRTree(String mapName) { - throw new InvalidOperationException("rtree not supported on mapdb store"); - } - - @Override - public String getStoreVersion() { - return "MapDB/" + getMapDbVersion(); - } - - private void initEventBus() { - if (getStoreConfig().eventListeners() != null) { - for (StoreEventListener eventListener : getStoreConfig().eventListeners()) { - eventBus.register(eventListener); - } - } - } - - private static String getMapDbVersion() { - return "3.0.8"; - } -} diff --git a/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/MapDBStoreType.java b/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/MapDBStoreType.java deleted file mode 100644 index b6dc86d98..000000000 --- a/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/MapDBStoreType.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.dizitart.no2.mapdb; - -/** - * @author Anindya Chatterjee - */ -public enum MapDBStoreType { - ByteArray, - DirectBuffer, - MemoryMappedFile, - RandomAccessFile, - FileChannel, -} diff --git a/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/StoreFactory.java b/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/StoreFactory.java deleted file mode 100644 index ebd6b5f7d..000000000 --- a/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/StoreFactory.java +++ /dev/null @@ -1,141 +0,0 @@ -package org.dizitart.no2.mapdb; - -import lombok.extern.slf4j.Slf4j; -import org.dizitart.no2.common.util.StringUtils; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.mapdb.serializers.Serializers; -import org.mapdb.DB; -import org.mapdb.DBMaker; - -import static org.dizitart.no2.common.util.StringUtils.isNullOrEmpty; - -/** - * @author Anindya Chatterjee - */ -@Slf4j -class StoreFactory { - private StoreFactory() {} - - public static DB open(MapDBConfig dbConfig) { - DBMaker.StoreType storeType; - boolean defaultConfig = true; - - if (dbConfig.storeType() != null) { - defaultConfig = false; - switch (dbConfig.storeType()) { - case DirectBuffer: - storeType = DBMaker.StoreType.directbuffer; - break; - case MemoryMappedFile: - storeType = DBMaker.StoreType.fileMMap; - break; - case RandomAccessFile: - storeType = DBMaker.StoreType.fileRaf; - break; - case FileChannel: - storeType = DBMaker.StoreType.fileChannel; - break; - default: - storeType = DBMaker.StoreType.bytearray; - break; - } - } else { - if (StringUtils.isNullOrEmpty(dbConfig.filePath())) { - // if no file specified, use on bytearray memory db - storeType = DBMaker.StoreType.bytearray; - } else { - storeType = DBMaker.StoreType.fileRaf; - } - } - - DBMaker.Maker maker = new DBMaker.Maker(storeType, dbConfig.volume(), - dbConfig.volumeExists(), dbConfig.filePath()); - - if (dbConfig.allocateStartSize() != null) { - defaultConfig = false; - maker.allocateStartSize(dbConfig.allocateStartSize()); - } - - if (dbConfig.allocateIncrement() != null) { - defaultConfig = false; - maker.allocateIncrement(dbConfig.allocateIncrement()); - } - - if (dbConfig.fileDeleteAfterClose() != null && dbConfig.fileDeleteAfterClose()) { - maker.fileDeleteAfterClose(); - } - - if (dbConfig.fileDeleteAfterOpen() != null && dbConfig.fileDeleteAfterOpen()) { - maker.fileDeleteAfterOpen(); - } - - if (dbConfig.isThreadSafe() != null && !dbConfig.isThreadSafe()) { - defaultConfig = false; - maker.concurrencyDisable(); - } - - if (dbConfig.concurrencyScale() != null) { - defaultConfig = false; - maker.concurrencyScale(dbConfig.concurrencyScale()); - } - - if (dbConfig.cleanerHack() != null && dbConfig.cleanerHack()) { - defaultConfig = false; - maker.cleanerHackEnable(); - } - - if (dbConfig.fileMmapPreclearDisable() != null && dbConfig.fileMmapPreclearDisable()) { - defaultConfig = false; - maker.fileMmapPreclearDisable(); - } - - if (dbConfig.fileLockWait() != null) { - defaultConfig = false; - maker.fileLockWait(dbConfig.fileLockWait()); - } - - if (dbConfig.fileMmapfIfSupported() != null && dbConfig.fileMmapfIfSupported()) { - defaultConfig = false; - maker.fileMmapEnableIfSupported(); - } - - if (dbConfig.closeOnJvmShutdown() != null && dbConfig.closeOnJvmShutdown()) { - maker.closeOnJvmShutdown(); - } - - if (dbConfig.closeOnJvmShutdownWeakReference() != null && dbConfig.closeOnJvmShutdownWeakReference()) { - maker.closeOnJvmShutdownWeakReference(); - } - - if (dbConfig.isReadOnly() != null && dbConfig.isReadOnly()) { - defaultConfig = false; - if (isNullOrEmpty(dbConfig.filePath())) { - throw new InvalidOperationException("unable create readonly in-memory database"); - } - maker.readOnly(); - } - - if (dbConfig.checksumStoreEnable() != null && dbConfig.checksumStoreEnable()) { - maker.checksumStoreEnable(); - } - - if (dbConfig.checksumHeaderBypass() != null && dbConfig.checksumHeaderBypass()) { - maker.checksumHeaderBypass(); - } - - if (!StringUtils.isNullOrEmpty(dbConfig.filePath()) && defaultConfig) { - maker.fileMmapEnableIfSupported() - .fileMmapPreclearDisable() - .cleanerHackEnable(); - } - - if (dbConfig.serializerRegistry() != null) { - dbConfig.serializerRegistry().forEach(Serializers::registerSerializer); - } - - DB db = maker.make(); - db.getStore().fileLoad(); - - return db; - } -} diff --git a/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/serializers/Serializers.java b/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/serializers/Serializers.java deleted file mode 100644 index 6a57e4736..000000000 --- a/nitrite-mapdb-adapter/src/main/java/org/dizitart/no2/mapdb/serializers/Serializers.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.dizitart.no2.mapdb.serializers; - -import org.mapdb.serializer.GroupSerializer; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author Anindya Chatterjee - */ -public class Serializers { - private static final Map> serializerRegistry; - private Serializers() { - } - - static { - serializerRegistry = new HashMap<>(); - } - - public static void registerSerializer(Class type, GroupSerializer serializer) { - serializerRegistry.put(type.getName(), serializer); - } - - public static GroupSerializer findSerializer(Class type) { - if (serializerRegistry.containsKey(type.getName())) { - return serializerRegistry.get(type.getName()); - } - return null; - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/BaseCollectionTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/BaseCollectionTest.java deleted file mode 100644 index f561e928e..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/BaseCollectionTest.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb; - -import lombok.extern.slf4j.Slf4j; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.WriteResult; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.nio.file.Files; -import java.nio.file.Paths; -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Collection; -import java.util.Locale; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.mapdb.DbTestOperations.getRandomTempDbFile; - -@Slf4j -@RunWith(value = Parameterized.class) -public abstract class BaseCollectionTest { - @Parameterized.Parameter - public boolean inMemory = false; - @Parameterized.Parameter(value = 1) - public boolean isSecured = false; - - protected Nitrite db; - protected NitriteCollection collection; - protected Document doc1, doc2, doc3; - protected SimpleDateFormat simpleDateFormat; - private final String fileName = getRandomTempDbFile(); - - @Rule - public Retry retry = new Retry(3); - - @Parameterized.Parameters(name = "InMemory = {0}, Protected = {1}") - public static Collection data() { - return Arrays.asList(new Object[][]{ - {false, false}, - {false, true}, - {true, false}, - {true, true}, - }); - } - - @Before - public void setUp() { - try { - openDb(); - - simpleDateFormat - = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); - - doc1 = createDocument("firstName", "fn1") - .put("lastName", "ln1") - .put("birthDay", simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) - .put("data", new byte[]{1, 2, 3}) - .put("list", Arrays.asList("one", "two", "three")) - .put("body", "a quick brown fox jump over the lazy dog"); - doc2 = createDocument("firstName", "fn2") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2010-06-12T16:02:48.440Z")) - .put("data", new byte[]{3, 4, 3}) - .put("list", Arrays.asList("three", "four", "three")) - .put("body", "quick hello world from nitrite"); - doc3 = createDocument("firstName", "fn3") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2014-04-17T16:02:48.440Z")) - .put("data", new byte[]{9, 4, 8}) - .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + - "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); - - collection = db.getCollection("test"); - collection.remove(ALL); - } catch (Throwable t) { - log.error("Error while initializing test database", t); - } - } - - @After - public void clear() { - try { - if (collection != null && !collection.isDropped()) { - collection.close(); - } - if (db != null && !db.isClosed()) db.close(); - if (!inMemory) { - Files.delete(Paths.get(fileName)); - } - } catch (Throwable t) { - log.error("Error while clearing test database", t); - } - } - - private void openDb() { - MapDBModuleBuilder builder = MapDBModule.withConfig(); - - if (!inMemory) { - builder.filePath(fileName); - } - - MapDBModule storeModule = builder.build(); - NitriteBuilder nitriteBuilder = Nitrite.builder() - .fieldSeparator(".") - .loadModule(storeModule); - - if (isSecured) { - db = nitriteBuilder.openOrCreate("test-user", "test-password"); - } else { - db = nitriteBuilder.openOrCreate(); - } - } - - protected WriteResult insert() { - return collection.insert(doc1, doc2, doc3); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/CollectionFieldIndexTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/CollectionFieldIndexTest.java deleted file mode 100644 index e558319bd..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/CollectionFieldIndexTest.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.index.IndexType; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.dizitart.no2.mapdb.TestUtil.createDb; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee - */ -public class CollectionFieldIndexTest { - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - db = createDb(); - } - - @Test - public void testCollection() { - Document doc1 = Document.createDocument("name", "Anindya") - .put("color", new String[]{"red", "green", "blue"}) - .put("books", new Document[]{ - Document.createDocument("name", "Book ABCD") - .put("tag", new String[]{"tag1", "tag2"}), - Document.createDocument("name", "Book EFGH") - .put("tag", new String[]{"tag3", "tag1"}), - Document.createDocument("name", "No Tag") - }); - - Document doc2 = Document.createDocument("name", "Bill") - .put("color", new String[]{"purple", "yellow", "gray"}) - .put("books", new Document[]{ - Document.createDocument("name", "Book abcd") - .put("tag", new String[]{"tag4", "tag5"}), - Document.createDocument("name", "Book wxyz") - .put("tag", new String[]{"tag3", "tag1"}), - Document.createDocument("name", "No Tag 2") - }); - - Document doc3 = Document.createDocument("name", "John") - .put("color", new String[]{"black", "sky", "violet"}) - .put("books", new Document[]{ - Document.createDocument("name", "Book Mnop") - .put("tag", new String[]{"tag6", "tag2"}), - Document.createDocument("name", "Book ghij") - .put("tag", new String[]{"tag3", "tag7"}), - Document.createDocument("name", "No Tag") - }); - - NitriteCollection collection = db.getCollection("test"); - collection.createIndex("color", indexOptions(IndexType.Unique)); - collection.createIndex("books.tag", indexOptions(IndexType.NonUnique)); - collection.createIndex("books.name", indexOptions(IndexType.Fulltext)); - - WriteResult writeResult = collection.insert(doc1, doc2, doc3); - assertEquals(writeResult.getAffectedCount(), 3); - - DocumentCursor documents = collection.find(where("color").eq("red")); - assertTrue(isSimilar(documents.firstOrNull(), doc1, "name", "color", "books")); - - documents = collection.find(where("books.name").text("abcd")); - assertEquals(documents.size(), 2); - - documents = collection.find(where("books.tag").eq("tag2")); - assertEquals(documents.size(), 2); - - documents = collection.find(where("books.tag").eq("tag5")); - assertEquals(documents.size(), 1); - - documents = collection.find(where("books.tag").eq("tag10")); - assertEquals(documents.size(), 0); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/CustomFilterTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/CustomFilterTest.java deleted file mode 100644 index ae96f5e74..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/CustomFilterTest.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb; - -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.index.IndexType; -import org.junit.Test; - -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class CustomFilterTest extends BaseCollectionTest { - - @Test - public void testCustomFilter() { - insert(); - collection.createIndex("firstName", indexOptions(IndexType.NonUnique)); - DocumentCursor cursor = collection.find(element -> element.getSecond().get("firstName", String.class) - .equalsIgnoreCase("FN1")); - - assertEquals(cursor.size(), 1); - assertEquals(cursor.firstOrNull().get("firstName"), "fn1"); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/DbTestOperations.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/DbTestOperations.java deleted file mode 100644 index a5592d420..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/DbTestOperations.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.index.IndexType; -import org.junit.Rule; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.*; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.dizitart.no2.mapdb.TestUtil.isSorted; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee. - */ -public class DbTestOperations { - private final String fileName = getRandomTempDbFile(); - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - public static String getRandomTempDbFile() { - String dataDir = System.getProperty("java.io.tmpdir") + File.separator + "nitrite" + File.separator + "data"; - File file = new File(dataDir); - if (!file.exists()) { - assertTrue(file.mkdirs()); - } - return file.getPath() + File.separator + UUID.randomUUID().toString() + ".db"; - } - - void createDb() { - db = TestUtil.createDb(fileName); - db.close(); - } - - void writeCollection() { - NitriteCollection collection; - - db = TestUtil.createDb(fileName); - - collection = db.getCollection("test"); - collection.remove(ALL); - db.close(); - } - - void writeIndex() { - NitriteCollection collection; - - db = TestUtil.createDb(fileName); - - collection = db.getCollection("test"); - collection.remove(ALL); - collection.createIndex("body", indexOptions(IndexType.Fulltext)); - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - db.close(); - } - - void insertInCollection() throws ParseException { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); - - Document doc1 = createDocument("firstName", "fn1") - .put("lastName", "ln1") - .put("birthDay", simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) - .put("data", new byte[]{1, 2, 3}) - .put("body", "a quick brown fox jump over the lazy dog"); - Document doc2 = createDocument("firstName", "fn2") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2010-06-12T16:02:48.440Z")) - .put("data", new byte[]{3, 4, 3}) - .put("body", "quick hello world from nitrite"); - Document doc3 = createDocument("firstName", "fn3") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2014-04-17T16:02:48.440Z")) - .put("data", new byte[]{9, 4, 8}) - .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + - "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); - - NitriteCollection collection; - - db = TestUtil.createDb(fileName); - - collection = db.getCollection("test"); - - WriteResult result = collection.insert(doc1, doc2, doc3); - assertEquals(result.getAffectedCount(), 3); - - db.commit(); - db.close(); - } - - void readCollection() throws ParseException { - NitriteCollection collection; - - db = TestUtil.createDb(fileName); - - collection = db.getCollection("test"); - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").gt(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").gte(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lt(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lte(new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").lt(new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").gt(new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").gte(new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").lte(new Date()).and(where("firstName").eq("fn1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte(new Date()).or(where("firstName").eq("fn12"))); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1")) - .not()); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").eq((byte) 4)); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").lt(4)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("firstName").notIn("fn1", "fn2")); - assertEquals(cursor.size(), 1); - - collection.createIndex("birthDay", indexOptions(IndexType.Unique)); - cursor = collection.find().sort("birthDay", SortOrder.Descending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, false)); - - cursor = collection.find(where("body").text("Lorem")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("body").text("quick")); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("body").text("nosql")); - assertEquals(cursor.size(), 0); - - db.close(); - } - - void deleteDb() throws IOException { - if (db != null && !db.isClosed()) { - db.close(); - } - Files.delete(Paths.get(fileName)); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/DbWriteCloseReadTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/DbWriteCloseReadTest.java deleted file mode 100644 index b8a11d845..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/DbWriteCloseReadTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb; - -import org.junit.Test; - -import java.text.ParseException; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * @author Anindya Chatterjee. - */ -public class DbWriteCloseReadTest { - private final DbTestOperations operations = new DbTestOperations(); - private volatile boolean writeCompleted = false; - -// @Rule -// public Retry retry = new Retry(3); - - @Test - public void testWriteCloseRead() throws Exception { - try { - operations.createDb(); - operations.writeCollection(); - operations.writeIndex(); - operations.insertInCollection(); - } catch (ParseException pe) { - // ignore - } finally { - writeCompleted = true; - } - - try { - assertTrue(writeCompleted); - operations.readCollection(); - } catch (Exception e) { - fail("collection read failed - " + e.getMessage()); - } finally { - operations.deleteDb(); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/DocumentMetadataTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/DocumentMetadataTest.java deleted file mode 100644 index 29a571830..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/DocumentMetadataTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.events.EventType; -import org.junit.Test; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee. - */ -public class DocumentMetadataTest extends BaseCollectionTest { - @Test - public void testTimeStamp() { - Document document = createDocument("test_key", "test_value"); - assertEquals(document.getRevision().intValue(), 0); - assertEquals(document.getLastModifiedSinceEpoch().longValue(), 0L); - - collection.insert(document); - document = collection.find().firstOrNull(); - - assertEquals(document.getRevision().intValue(), 1); - assertTrue(document.getLastModifiedSinceEpoch() > 0); - - long previous = document.getRevision(); - - DocumentCursor cursor = collection.find(where("test_key").eq("test_value")); - document = cursor.firstOrNull(); - document.put("another_key", "another_value"); - - collection.update(document); - cursor = collection.find(where("test_key").eq("test_value")); - document = cursor.firstOrNull(); - - assertTrue(document.getRevision() > previous); - - final long time = document.getRevision(); - final Document removed = document; - - collection.subscribe(changeInfo -> { - if (changeInfo.getEventType() == EventType.Remove) { - assertTrue(removed.getRevision() > time); - } - }); - - collection.remove(document); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/MapDBConfigTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/MapDBConfigTest.java deleted file mode 100644 index 24791976a..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/MapDBConfigTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.dizitart.no2.mapdb; - -import org.junit.Test; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; - -public class MapDBConfigTest { - @Test - public void testConstructor() { - MapDBConfig actualMapDBConfig = new MapDBConfig(); - assertNull(actualMapDBConfig.isThreadSafe()); - assertNull(actualMapDBConfig.volume()); - assertFalse(actualMapDBConfig.isReadOnly()); - } -} - diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/MapDBModuleBuilderTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/MapDBModuleBuilderTest.java deleted file mode 100644 index 8d7da0824..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/MapDBModuleBuilderTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.dizitart.no2.mapdb; - -import org.junit.Test; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; - -public class MapDBModuleBuilderTest { - @Test - public void testConstructor() { - MapDBModuleBuilder actualMapDBModuleBuilder = new MapDBModuleBuilder(); - assertNull(actualMapDBModuleBuilder.isThreadSafe()); - assertNull(actualMapDBModuleBuilder.volume()); - assertFalse(actualMapDBModuleBuilder.readOnly()); - } -} - diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/MapDBModuleTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/MapDBModuleTest.java deleted file mode 100644 index 6f39214d9..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/MapDBModuleTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.dizitart.no2.mapdb; - -import org.junit.Test; - -import static org.junit.Assert.*; - -public class MapDBModuleTest { - @Test - public void testWithConfig() { - MapDBModuleBuilder actualWithConfigResult = MapDBModule.withConfig(); - assertNull(actualWithConfigResult.isThreadSafe()); - assertNull(actualWithConfigResult.volume()); - assertFalse(actualWithConfigResult.readOnly()); - } - - @Test - public void testGetStore() { - assertTrue((new MapDBModule("path")).getStore() instanceof MapDBStore); - } - - @Test - public void testPlugins() { - assertEquals(1, (new MapDBModule("path")).plugins().size()); - } -} - diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/MapDBStoreTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/MapDBStoreTest.java deleted file mode 100644 index 5e9be9643..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/MapDBStoreTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.dizitart.no2.mapdb; - -import org.junit.Test; - -import static org.junit.Assert.*; - -public class MapDBStoreTest { - @Test - public void testConstructor() { - MapDBStore actualMapDBStore = new MapDBStore(); - assertNull(actualMapDBStore.getStoreConfig()); - assertEquals("MapDB/3.0.8", actualMapDBStore.getStoreVersion()); - assertFalse(actualMapDBStore.hasUnsavedChanges()); - assertTrue(actualMapDBStore.isClosed()); - } - - @Test - public void testIsClosed() { - assertTrue((new MapDBStore()).isClosed()); - } - - @Test - public void testHasUnsavedChanges() { - assertFalse((new MapDBStore()).hasUnsavedChanges()); - } - - @Test - public void testGetStoreVersion() { - assertEquals("MapDB/3.0.8", (new MapDBStore()).getStoreVersion()); - } -} - diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/MapDBStoreTypeTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/MapDBStoreTypeTest.java deleted file mode 100644 index a3e6ec7fb..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/MapDBStoreTypeTest.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.dizitart.no2.mapdb; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class MapDBStoreTypeTest { - @Test - public void testValueOf() { - assertEquals(MapDBStoreType.ByteArray, MapDBStoreType.valueOf("ByteArray")); - } - - @Test - public void testValues() { - assertEquals(5, MapDBStoreType.values().length); - } -} - diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/MultiThreadedTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/MultiThreadedTest.java deleted file mode 100644 index 562698815..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/MultiThreadedTest.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.concurrent.ThreadPoolManager; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.io.File; -import java.util.*; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.mapdb.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.mapdb.TestUtil.createDb; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - - -/** - * @author Anindya Chatterjee. - */ -@RunWith(Parameterized.class) -public class MultiThreadedTest { - private static final String fileName = getRandomTempDbFile(); - @Parameterized.Parameter - public boolean inMemory = false; - private NitriteCollection collection; - private final int threadCount = 20; - private final CountDownLatch latch = new CountDownLatch(threadCount); - private final int iterationCount = 100; - private final Random generator = new Random(); - private final AtomicInteger docCounter = new AtomicInteger(0); - private ExecutorService executor = ThreadPoolManager.getThreadPool(threadCount, "MultiThreadedTest"); - private Nitrite db; - - @Parameterized.Parameters(name = "InMemory = {0}") - public static Collection data() { - return Arrays.asList(new Object[][]{ - {false}, - {true} - }); - } - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testOperations() throws InterruptedException { - db = inMemory ? createDb() : createDb(fileName); - - collection = db.getCollection("test"); - collection.remove(Filter.ALL); - collection.createIndex("unixTime", IndexOptions.indexOptions(IndexType.Unique)); - db.commit(); - - for (int i = 0; i < threadCount; i++) { - executor.submit(() -> { - for (int j = 0; j < iterationCount; j++) { - try { - Document document = generate(); - collection.insert(document); - - if (j == iterationCount / 2 - && !collection.hasIndex("text") - && !collection.hasIndex("date")) { - collection.createIndex("text", IndexOptions.indexOptions(IndexType.Fulltext)); - collection.createIndex("date", IndexOptions.indexOptions(IndexType.NonUnique)); - } - - long unixTime = (long) document.get("unixTime"); - DocumentCursor cursor = collection.find(where("unixTime").eq(unixTime)); - assertTrue(cursor.size() >= 0); - - if (collection.hasIndex("text") && !collection.isIndexing("text")) { - String textData = (String) document.get("text"); - cursor = collection.find(where("text").text(textData)); - assertTrue(cursor.size() >= 0); - } - - assertTrue(collection.hasIndex("unixTime")); - } catch (Throwable e) { - System.out.println("Exception at thread " + - Thread.currentThread().getName() + " with iteration " + j); - e.printStackTrace(); - } - } - latch.countDown(); - }); - } - - latch.await(); - - db.commit(); - - assertTrue(collection.hasIndex("text")); - assertTrue(collection.hasIndex("date")); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), docCounter.get()); - - cursor = collection.find(where("unixTime").gt(1L)); - assertEquals(cursor.size(), docCounter.get()); - - db.close(); - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - - if (!inMemory) { - File dbFile = new File(fileName); - long fileSize = dbFile.length(); - assertTrue(fileSize > 0); - dbFile.delete(); - } - - if (executor != null && !executor.isShutdown()) { - executor.shutdown(); - executor = null; - } - } - - private synchronized Document generate() { - Document document = createDocument("unixTime", System.nanoTime() + docCounter.incrementAndGet()); - byte[] blob = new byte[1024]; - generator.nextBytes(blob); - document.put("blob", blob); - document.put("text", UUID.randomUUID().toString().replaceAll("-", " ")); - document.put("date", new Date()); - return document; - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteBuilderNegativeTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteBuilderNegativeTest.java deleted file mode 100644 index 92ac2bfcf..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteBuilderNegativeTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb; - -import org.apache.commons.io.FileUtils; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.common.util.StringUtils; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.io.File; - -import static org.dizitart.no2.mapdb.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.mapdb.TestUtil.createDb; - -/** - * @author Anindya Chatterjee. - */ -public class NitriteBuilderNegativeTest { - private Nitrite db; - private String filePath; - - @Rule - public Retry retry = new Retry(3); - - @Test(expected = NitriteIOException.class) - public void testCreateReadonlyDatabase() { - filePath = getRandomTempDbFile(); - - MapDBModule storeModule = MapDBModule.withConfig() - .filePath(filePath) - .readOnly(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .openOrCreate(); - db.close(); - } - - @Test(expected = InvalidOperationException.class) - public void testCreateReadonlyInMemoryDatabase() { - MapDBModule storeModule = MapDBModule.withConfig() - .readOnly(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .openOrCreate(); - db.close(); - } - - @Test(expected = NitriteIOException.class) - public void testOpenWithLock() { - filePath = getRandomTempDbFile(); - - db = createDb(filePath); - db = createDb(filePath); - } - - @Test(expected = NitriteIOException.class) - public void testInvalidDirectory() { - filePath = "/ytgr/hfurh/frij.db"; - db = createDb(filePath); - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - - if (!StringUtils.isNullOrEmpty(filePath)) { - FileUtils.deleteQuietly(new File(filePath)); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteBuilderTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteBuilderTest.java deleted file mode 100644 index 26d80df47..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteBuilderTest.java +++ /dev/null @@ -1,426 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.NitriteConfig; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.SecurityException; -import org.dizitart.no2.index.Indexer; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.store.NitriteMap; -import org.dizitart.no2.store.StoreConfig; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Random; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.common.util.StringUtils.isNullOrEmpty; -import static org.dizitart.no2.mapdb.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.mapdb.TestUtil.createDb; -import static org.dizitart.no2.module.NitriteModule.module; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class NitriteBuilderTest { - private String fakeFile; - private String filePath; - private Nitrite db; - private Nitrite fakeDb; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void startup() { - fakeFile = getRandomTempDbFile(); - filePath = getRandomTempDbFile(); - } - - @After - public void cleanup() throws IOException { - (new NitriteConfig()).fieldSeparator("."); - - if (db != null && !db.isClosed()) { - db.close(); - } - - if (Files.exists(Paths.get(filePath))) { - Files.delete(Paths.get(filePath)); - } - - if (fakeDb != null && !fakeDb.isClosed()){ - fakeDb.close(); - } - - if (Files.exists(Paths.get(fakeFile))) { - Files.delete(Paths.get(fakeFile)); - } - } - - @Test - public void testConfig() throws IOException { - MapDBModuleBuilder builder = MapDBModule.withConfig(); - builder.filePath(filePath); - - NitriteBuilder nitriteBuilder = Nitrite.builder(); - nitriteBuilder.loadModule(module(new CustomIndexer())); - nitriteBuilder.loadModule(builder.build()); - - db = nitriteBuilder.openOrCreate(); - NitriteConfig config = nitriteBuilder.getNitriteConfig(); - MapDBConfig storeConfig = (MapDBConfig) db.getStore().getStoreConfig(); - - assertEquals(config.findIndexer("Custom").getClass(), CustomIndexer.class); - assertFalse(storeConfig.isReadOnly()); - assertFalse(storeConfig.isInMemory()); - assertFalse(isNullOrEmpty(storeConfig.filePath())); - - db.close(); - - builder = MapDBModule.withConfig() - .readOnly(true) - .filePath(filePath); - - db = Nitrite.builder().loadModule(builder.build()).openOrCreate(); - - storeConfig = (MapDBConfig) db.getStore().getStoreConfig(); - assertTrue(storeConfig.isReadOnly()); - db.close(); - - Files.delete(Paths.get(filePath)); - } - - @Test - public void testConfigWithFile() { - File file = new File(filePath); - MapDBModule storeModule = MapDBModule.withConfig() - .filePath(file) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .openOrCreate(); - StoreConfig storeConfig = db.getStore().getStoreConfig(); - - assertFalse(storeConfig.isInMemory()); - assertFalse(isNullOrEmpty(storeConfig.filePath())); - - NitriteCollection test = db.getCollection("test"); - assertNotNull(test); - - db.commit(); - db.close(); - - assertTrue(file.delete()); - } - - @Test - public void testConfigWithFileNull() { - File file = null; - MapDBModule module = MapDBModule.withConfig() - .filePath(file) - .build(); - - db = Nitrite.builder().loadModule(module).openOrCreate(); - StoreConfig storeConfig = db.getStore().getStoreConfig(); - - assertTrue(storeConfig.isInMemory()); - assertTrue(isNullOrEmpty(storeConfig.filePath())); - - NitriteCollection test = db.getCollection("test"); - assertNotNull(test); - - db.commit(); - db.close(); - } - - @Test - public void testPopulateRepositories() { - File file = new File(filePath); - MapDBModule module = MapDBModule.withConfig().filePath(file).build(); - db = Nitrite.builder() - .fieldSeparator(".") - .loadModule(module) - .openOrCreate(); - - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("id1", "value")); - - ObjectRepository repository = db.getRepository(TestObject.class); - repository.insert(new TestObject("test", 1L)); - - ObjectRepository repository2 = db.getRepository(TestObject.class, "key"); - TestObject object = new TestObject(); - object.stringValue = "test2"; - object.longValue = 2L; - repository2.insert(object); - - ObjectRepository repository3 = db.getRepository(TestObject2.class, "key"); - TestObject2 object2 = new TestObject2(); - object2.stringValue = "test2"; - object2.longValue = 2L; - repository3.insert(object2); - - db.commit(); - db.close(); - - db = Nitrite.builder() - .loadModule(module) - .fieldSeparator(".") - .openOrCreate(); - assertTrue(db.hasCollection("test")); - assertTrue(db.hasRepository(TestObject.class)); - assertTrue(db.hasRepository(TestObject.class, "key")); - assertFalse(db.hasRepository(TestObject2.class)); - assertTrue(db.hasRepository(TestObject2.class, "key")); - } - - - @Test - public void testNitriteMapper() { - NitriteBuilder builder = Nitrite.builder(); - builder.loadModule(module(new CustomNitriteMapper())); - NitriteConfig config = builder.getNitriteConfig(); - assertNotNull(config.nitriteMapper()); - } - - @Test(expected = SecurityException.class) - public void testOpenOrCreateNullUserId() { - NitriteBuilder builder = Nitrite.builder(); - builder.openOrCreate(null, "abcd"); - } - - @Test(expected = SecurityException.class) - public void testOpenOrCreateNullPassword() { - NitriteBuilder builder = Nitrite.builder(); - builder.openOrCreate("abcd", null); - } - - @Test(expected = NitriteIOException.class) - public void testDbCorruption() throws IOException { - File file = new File(fakeFile); - FileWriter writesToFile; - // Create file writer object - writesToFile = new FileWriter(file); - // Wrap the writer with buffered streams - BufferedWriter writer = new BufferedWriter(writesToFile); - int line; - Random rand = new Random(); - for (int j = 0; j < 10; j++) { - // Randomize an integer and write it to the output file - line = rand.nextInt(50000); - writer.write(line + "\n"); - } - // Close the stream - writer.close(); - - fakeDb = createDb(fakeFile); - assertNull(fakeDb); - } - - @Test(expected = InvalidOperationException.class) - public void testDbInMemoryReadonly() { - MapDBModule module = MapDBModule.withConfig() - .readOnly(true) - .build(); - - fakeDb = Nitrite.builder() - .loadModule(module) - .openOrCreate(); - assertNull(fakeDb); - } - - @Test(expected = NitriteIOException.class) - public void testDbInvalidDirectory() { - fakeFile = System.getProperty("java.io.tmpdir") + File.separator + "fake" + File.separator + "fake.db"; - db = createDb(fakeFile, "test", "test"); - assertNull(db); - } - - @Test - public void testFieldSeparator() { - MapDBModule module = MapDBModule.withConfig() - .filePath(filePath) - .build(); - db = Nitrite.builder() - .loadModule(module) - .fieldSeparator("::") - .openOrCreate(); - - Document document = createDocument("firstName", "John") - .put("colorCodes", new Document[]{createDocument("color", "Red"), createDocument("color", "Green")}) - .put("address", createDocument("street", "ABCD Road")); - - String street = document.get("address::street", String.class); - assertEquals("ABCD Road", street); - - // use default separator, it should return null - street = document.get("address.street", String.class); - assertNull(street); - - assertEquals(document.get("colorCodes::1::color"), "Green"); - } - - @Test(expected = NitriteIOException.class) - public void testInvalidPath() { - MapDBModule module = MapDBModule.withConfig() - .filePath("http://www.localhost.com") - .build(); - - db = Nitrite.builder() - .loadModule(module) - .openOrCreate("test", "test"); - assertNull(db); - } - - private static class CustomIndexer implements Indexer { - - @Override - public String getIndexType() { - return "Custom"; - } - - @Override - public void writeIndex(NitriteMap collection, NitriteId nitriteId, String field, Object fieldValue) { - - } - - @Override - public void removeIndex(NitriteMap collection, NitriteId nitriteId, String field, Object fieldValue) { - - } - - @Override - public void updateIndex(NitriteMap collection, NitriteId nitriteId, String field, Object newValue, Object oldValue) { - - } - - @Override - public void dropIndex(NitriteMap collection, String field) { - - } - - @Override - public Indexer clone() throws CloneNotSupportedException { - return null; - } - - @Override - public void initialize(NitriteConfig nitriteConfig) { - - } - } - - public static class CustomNitriteMapper implements NitriteMapper { - - @Override - public Target convert(Source source, Class type) { - return null; - } - - @Override - public boolean isValueType(Class type) { - return false; - } - - @Override - public boolean isValue(Object object) { - return false; - } - - @Override - public void initialize(NitriteConfig nitriteConfig) { - - } - } - - @Index(value = "longValue") - private static class TestObject implements Mappable { - private String stringValue; - private Long longValue; - - public TestObject() { - } - - public TestObject(String stringValue, Long longValue) { - this.longValue = longValue; - this.stringValue = stringValue; - } - - @Override - public Document write(NitriteMapper mapper) { - return createDocument("stringValue", stringValue) - .put("longValue", longValue); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - if (document != null) { - this.stringValue = document.get("stringValue", String.class); - this.longValue = document.get("longValue", Long.class); - } - } - } - - @Index(value = "longValue") - private static class TestObject2 implements Mappable { - private String stringValue; - private Long longValue; - - public TestObject2() { - } - - public TestObject2(String stringValue, Long longValue) { - this.longValue = longValue; - this.stringValue = stringValue; - } - - @Override - public Document write(NitriteMapper mapper) { - return createDocument("stringValue", stringValue) - .put("longValue", longValue); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - if (document != null) { - this.stringValue = document.get("stringValue", String.class); - this.longValue = document.get("longValue", Long.class); - } - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteCorruptedTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteCorruptedTest.java deleted file mode 100644 index c88436a61..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteCorruptedTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.concurrent.ThreadPoolManager; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.concurrent.ExecutorService; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.mapdb.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.mapdb.TestUtil.createDb; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee - */ -public class NitriteCorruptedTest { - private Nitrite db; - private NitriteCollection collection; - private final String fileName = getRandomTempDbFile(); - private Thread thread; - private final ExecutorService dbPool = ThreadPoolManager.getThreadPool(Runtime.getRuntime().availableProcessors(), - "NitriteCorruptedTest"); - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - db = createDb(fileName); - - collection = db.getCollection("test"); - collection.remove(ALL); - - thread = new Thread(() -> { - for (int i = 0; i < 50000; i++) { - - // Interruption Guard - if (Thread.interrupted()) { - break; - } - - Document doc1 = createDocument(String.valueOf(System.currentTimeMillis()), "fn1") - .put("lastName", "ln1") - .put("data", new byte[]{1, 2, 3}) - .put("body", "a quick brown fox jump over the lazy dog"); - - // Separate user thread from Db write thread - dbPool.submit(() -> collection.insert(doc1)); - } - }); - } - - @After - public void tearDown() throws IOException { - if (collection.isOpen()) { - collection.remove(ALL); - collection.close(); - } - db.close(); - Files.delete(Paths.get(fileName)); - } - - @Test(timeout = 10000) - public void issue118() throws InterruptedException { - thread.start(); - Thread.sleep(10); - thread.interrupt(); - Thread.sleep(500); - assertTrue(collection.isOpen()); - assertFalse(db.isClosed()); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteStoreFactoryNegativeTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteStoreFactoryNegativeTest.java deleted file mode 100644 index 01859692d..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteStoreFactoryNegativeTest.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb; - -import org.apache.commons.io.FileUtils; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.exceptions.NitriteException; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.io.File; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.mapdb.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.mapdb.TestUtil.createDb; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class NitriteStoreFactoryNegativeTest { - private Nitrite db; - private final String fileName = getRandomTempDbFile(); - - @Rule - public Retry retry = new Retry(3); - - @Test(expected = NitriteException.class) - public void testOpenSecuredWithoutCredential() { - db = createDb(fileName, "test-user", "test-password"); - NitriteCollection dbCollection = db.getCollection("test"); - dbCollection.insert(createDocument("test", "test")); - db.commit(); - db.close(); - - db = createDb(fileName); - dbCollection = db.getCollection("test"); - assertEquals(dbCollection.find().size(), 1); - } - - @Test(expected = NitriteException.class) - public void testOpenUnsecuredWithCredential() { - db = createDb(fileName); - NitriteCollection dbCollection = db.getCollection("test"); - dbCollection.insert(createDocument("test", "test")); - db.commit(); - db.close(); - - db = createDb(fileName, "test-user", "test-password"); - dbCollection = db.getCollection("test"); - assertEquals(dbCollection.find().size(), 1); - } - - @Test(expected = NitriteException.class) - public void testWrongCredential() { - db = createDb(fileName, "test-user", "test-password"); - NitriteCollection dbCollection = db.getCollection("test"); - dbCollection.insert(createDocument("test", "test")); - db.commit(); - db.close(); - - db = createDb(fileName, "test-user", "test-password2"); - dbCollection = db.getCollection("test"); - assertEquals(dbCollection.find().size(), 1); - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - - FileUtils.deleteQuietly(new File(fileName)); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteStoreFactoryTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteStoreFactoryTest.java deleted file mode 100644 index 7eb871223..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteStoreFactoryTest.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb; - -import org.apache.commons.io.FileUtils; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.exceptions.SecurityException; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.mapdb.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.mapdb.TestUtil.createDb; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee. - */ -public class NitriteStoreFactoryTest { - private Nitrite db; - private final String fileName = getRandomTempDbFile(); - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testSecured() throws IOException { - db = createDb(fileName, "test-user", "test-password"); - NitriteCollection dbCollection = db.getCollection("test"); - dbCollection.insert(createDocument("test", "test")); - db.commit(); - db.close(); - - db = createDb(fileName, "test-user", "test-password"); - dbCollection = db.getCollection("test"); - assertEquals(dbCollection.find().size(), 1); - db.close(); - Files.delete(Paths.get(fileName)); - } - - @Test - public void testUnsecured() throws IOException { - db = createDb(fileName); - NitriteCollection dbCollection = db.getCollection("test"); - dbCollection.insert(createDocument("test", "test")); - db.commit(); - db.close(); - - db = createDb(fileName); - dbCollection = db.getCollection("test"); - assertEquals(dbCollection.find().size(), 1); - db.close(); - Files.delete(Paths.get(fileName)); - } - - @Test - public void testInMemory() { - db = createDb("test-user", "test-password"); - NitriteCollection dbCollection = db.getCollection("test"); - dbCollection.insert(createDocument("test", "test")); - db.commit(); - assertEquals(dbCollection.find().size(), 1); - db.close(); - - db = createDb(); - dbCollection = db.getCollection("test"); - assertEquals(dbCollection.find().size(), 0); - db.close(); - } - - @Test - public void testIssue116() throws IOException { - db = createDb(fileName, "test-user", "test-password"); - db.close(); - try { - db = createDb(fileName,"test-user2", "test-password2"); - } catch (SecurityException se) { - db = createDb(fileName,"test-user", "test-password"); - assertNotNull(db); - } finally { - db.close(); - Files.delete(Paths.get(fileName)); - } - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - - FileUtils.deleteQuietly(new File(fileName)); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteStressTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteStressTest.java deleted file mode 100644 index e813fbb31..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteStressTest.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb; - -import lombok.Data; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Id; -import org.junit.Rule; -import org.junit.Test; -import uk.co.jemos.podam.api.PodamFactory; -import uk.co.jemos.podam.api.PodamFactoryImpl; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlSchemaType; -import java.util.ArrayList; -import java.util.List; - -import static org.dizitart.no2.mapdb.TestUtil.createDb; - - -/** - * @author Anindya Chatterjee - */ -public class NitriteStressTest { - private static final int TEST_SET_COUNT = 15000; - private final PodamFactory podamFactory = new PodamFactoryImpl(); - - @Rule - public Retry retry = new Retry(3); - - @Test - public void stressTest() { - Nitrite database = createDb(); - ObjectRepository testRepository = database.getRepository(TestDto.class); - testRepository.createIndex("lastName", IndexOptions.indexOptions(IndexType.Fulltext)); - testRepository.createIndex("birthDate", IndexOptions.indexOptions(IndexType.NonUnique)); - - int counter = 0; - try { - for (TestDto testDto : createTestSet()) { - testRepository.insert(testDto); - counter++; - } - } catch (Throwable t) { - System.err.println("Crashed after " + counter + " records"); - throw t; - } - } - - private List createTestSet() { - List testData = new ArrayList<>(); - for (int i = 0; i < TEST_SET_COUNT; i++) { - TestDto testRecords = podamFactory.manufacturePojo(TestDto.class); - testData.add(testRecords); - } - return testData; - } - - @Data - public static class TestDto implements Mappable { - - @XmlElement( - name = "StudentNumber", - required = true - ) - @Id - protected String studentNumber; - - @XmlElement( - name = "LastName", - required = true - ) - protected String lastName; - - @XmlElement( - name = "Prefixes" - ) - protected String prefixes; - - @XmlElement( - name = "Initials", - required = true - ) - protected String initials; - - @XmlElement( - name = "FirstNames" - ) - protected String firstNames; - @XmlElement( - name = "Nickname" - ) - protected String nickName; - - @XmlElement( - name = "BirthDate", - required = true - ) - @XmlSchemaType( - name = "date" - ) - protected String birthDate; - - - public TestDto() { - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("studentNumber", studentNumber) - .put("lastName", lastName) - .put("prefixes", prefixes) - .put("initials", initials) - .put("firstNames", firstNames) - .put("nickName", nickName) - .put("birthDate", birthDate); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - studentNumber = document.get("studentNumber", String.class); - lastName = document.get("lastName", String.class); - prefixes = document.get("prefixes", String.class); - initials = document.get("initials", String.class); - firstNames = document.get("firstNames", String.class); - nickName = document.get("nickName", String.class); - birthDate = document.get("birthDate", String.class); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteTest.java deleted file mode 100644 index 3aec455be..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/NitriteTest.java +++ /dev/null @@ -1,461 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.UpdateOptions; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.common.concurrent.ThreadPoolManager; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import uk.co.jemos.podam.api.PodamFactory; -import uk.co.jemos.podam.api.PodamFactoryImpl; - -import java.io.IOException; -import java.nio.file.Files; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Locale; -import java.util.Random; -import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; - -import static java.nio.file.Paths.get; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.common.Constants.INTERNAL_NAME_SEPARATOR; -import static org.dizitart.no2.common.Constants.META_MAP_NAME; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.mapdb.DbTestOperations.getRandomTempDbFile; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class NitriteTest { - private Nitrite db; - private NitriteCollection collection; - private SimpleDateFormat simpleDateFormat; - private final String fileName = getRandomTempDbFile(); - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() throws ParseException { - db = TestUtil.createDb(fileName, "test-user", "test-password"); - - simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); - - Document doc1 = createDocument("firstName", "fn1") - .put("lastName", "ln1") - .put("birthDay", simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) - .put("data", new byte[]{1, 2, 3}) - .put("body", "a quick brown fox jump over the lazy dog"); - Document doc2 = createDocument("firstName", "fn2") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2010-06-12T16:02:48.440Z")) - .put("data", new byte[]{3, 4, 3}) - .put("body", "hello world from nitrite"); - Document doc3 = createDocument("firstName", "fn3") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2014-04-17T16:02:48.440Z")) - .put("data", new byte[]{9, 4, 8}) - .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + - "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); - - collection = db.getCollection("test"); - collection.remove(ALL); - - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.Unique)); - collection.insert(doc1, doc2, doc3); - } - - @After - public void tearDown() throws IOException { - if (collection.isOpen()) { - collection.remove(ALL); - collection.close(); - } - if (db != null && !db.isClosed()) { - try { - db.close(); - } catch (NitriteIOException ignore) { - } - } - Files.delete(get(fileName)); - } - - @Test - public void testListCollectionNames() { - Set collectionNames = db.listCollectionNames(); - assertEquals(collectionNames.size(), 1); - } - - @Test - public void testListRepositories() { - db.getRepository(getClass()); - Set repositories = db.listRepositories(); - assertEquals(repositories.size(), 1); - } - - @Test - public void testHasCollection() { - assertTrue(db.hasCollection("test")); - assertFalse(db.hasCollection("lucene" + INTERNAL_NAME_SEPARATOR + "test")); - } - - @Test - public void testHasRepository() { - db.getRepository(getClass()); - assertTrue(db.hasRepository(getClass())); - assertFalse(db.hasRepository(String.class)); - } - - - @Test - public void testReopen() throws ParseException { - assertNotNull(db); - NitriteCollection testCollection = db.getCollection("test"); - assertNotNull(testCollection); - long prevSize = testCollection.find().size(); - - db.close(); - - db = null; - - db = TestUtil.createDb(fileName, "test-user", "test-password"); - - assertNotNull(db); - testCollection = db.getCollection("test"); - assertNotNull(testCollection); - long sizeNow = testCollection.find().size(); - assertEquals(prevSize, sizeNow); - - db.close(); - db = null; - db = TestUtil.createDb(fileName, "test-user", "test-password"); - - testCollection = db.getCollection("test"); - testCollection.insert(createDocument("firstName", "fn12") - .put("lastName", "ln12") - .put("birthDay", simpleDateFormat.parse("2010-07-01T16:02:48.440Z")) - .put("data", new byte[]{10, 20, 30}) - .put("body", "a quick brown fox jump over the lazy dog")); - - db.close(); - db = null; - db = TestUtil.createDb(fileName, "test-user", "test-password"); - - testCollection = db.getCollection("test"); - assertNotNull(testCollection); - sizeNow = testCollection.find().size(); - assertEquals(prevSize + 1, sizeNow); - } - - @Test - public void testClose() { - NitriteCollection testCollection = db.getCollection("test"); - testCollection.insert(createDocument("a", "b")); - db.close(); - - assertFalse(testCollection.isOpen()); - } - - @Test(expected = NitriteIOException.class) - public void testCloseReadonlyDatabase() { - db.close(); - db = null; - - MapDBModule storeModule = MapDBModule.withConfig() - .filePath(fileName) - .readOnly(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate("test-user", "test-password"); - NitriteCollection testCollection = db.getCollection("test"); - testCollection.insert(createDocument("a", "b")); - db.close(); - - assertFalse(testCollection.isOpen()); - } - - @Test - public void testGetCollection() { - NitriteCollection collection = db.getCollection("test-collection"); - assertNotNull(collection); - assertEquals(collection.getName(), "test-collection"); - } - - @Test - public void testGetRepository() { - ObjectRepository repository = db.getRepository(NitriteTest.class); - assertNotNull(repository); - assertEquals(repository.getType(), NitriteTest.class); - } - - @Test - public void testGetRepositoryWithKey() { - ObjectRepository repository = db.getRepository(NitriteTest.class, "key"); - assertNotNull(repository); - assertEquals(repository.getType(), NitriteTest.class); - assertFalse(db.hasRepository(NitriteTest.class)); - assertTrue(db.hasRepository(NitriteTest.class, "key")); - } - - @Test - public void testMultipleGetCollection() { - NitriteCollection collection = db.getCollection("test-collection"); - assertNotNull(collection); - assertEquals(collection.getName(), "test-collection"); - - NitriteCollection collection2 = db.getCollection("test-collection"); - assertNotNull(collection2); - assertEquals(collection2.getName(), "test-collection"); - } - - @Test - public void testMultipleGetRepository() { - ObjectRepository repository = db.getRepository(NitriteTest.class); - assertNotNull(repository); - assertEquals(repository.getType(), NitriteTest.class); - - ObjectRepository repository2 = db.getRepository(NitriteTest.class); - assertNotNull(repository2); - assertEquals(repository2.getType(), NitriteTest.class); - } - - @Test(expected = ValidationException.class) - public void testGetRepositoryInvalid() { - db.getRepository(null); - } - - @Test(expected = NitriteIOException.class) - public void testGetCollectionNullStore() { - db = Nitrite.builder().openOrCreate(); - db.close(); - db.getCollection("test"); - } - - @Test(expected = NitriteIOException.class) - public void testGetRepositoryNullStore() { - db = Nitrite.builder().openOrCreate(); - db.close(); - db.getRepository(NitriteTest.class); - } - - @Test(expected = NitriteIOException.class) - public void testGetKeyedRepositoryNullStore() { - db = Nitrite.builder().openOrCreate(); - db.close(); - db.getRepository(NitriteTest.class, "key"); - } - - @Test(expected = NitriteIOException.class) - public void testCommitNullStore() { - db = Nitrite.builder().openOrCreate(); - db.close(); - db.commit(); - } - - @Test(expected = ValidationException.class) - public void testGetCollectionInvalidName() { - db.getCollection(META_MAP_NAME); - } - - @Test(expected = NitriteIOException.class) - public void testIssue112() { - MapDBModule storeModule = MapDBModule.withConfig() - .filePath(System.getProperty("java.io.tmpdir")) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(); - assertNull(db); - } - - @Test - public void testIssue185() throws InterruptedException { - final ObjectRepository repository = db.getRepository(Receipt.class); - final Receipt receipt = new Receipt(); - receipt.clientRef = "111-11111"; - receipt.status = Receipt.Status.PREPARING; - CountDownLatch latch = new CountDownLatch(1); - - new Thread(() -> { - for (int i = 0; i < 1000; ++i) { - try { - repository.update(receipt, true); - try { - Thread.sleep(50); - } catch (InterruptedException ignored) { - } - repository.remove(receipt); - try { - Thread.sleep(50); - } catch (InterruptedException ignored) { - } - } catch (Throwable t) { - t.printStackTrace(); - } - } - latch.countDown(); - }).start(); - - for (int i = 0; i < 1000; ++i) { - repository.find(where("status").eq(Receipt.Status.COMPLETED).not()) - .sort("createdTimestamp", SortOrder.Descending).toList(); - try { - Thread.sleep(50); - } catch (InterruptedException ignored) { - } - } - latch.await(); - } - - @Test - public void testIssue193() throws InterruptedException { - final ObjectRepository repository = db.getRepository(Receipt.class); - final PodamFactory factory = new PodamFactoryImpl(); - final String[] refs = new String[]{"1", "2", "3", "4", "5"}; - final Random random = new Random(); - ExecutorService pool = ThreadPoolManager.workerPool(); - - final CountDownLatch latch = new CountDownLatch(10000); - for (int i = 0; i < 10000; i++) { - pool.submit(() -> { - int refIndex = random.nextInt(5); - Receipt receipt = factory.manufacturePojoWithFullData(Receipt.class); - receipt.setClientRef(refs[refIndex]); - repository.update(receipt, true); - latch.countDown(); - }); - } - - latch.await(); - assertTrue(repository.find().size() <= 5); - pool.shutdown(); - } - - @Test - public void testIssue212() { - NitriteCollection collection = db.getCollection("testIssue212"); - Document doc1 = createDocument("key", "key").put("second_key", "second_key").put("third_key", "third_key"); - Document doc2 = createDocument("key", "key").put("second_key", "second_key").put("fourth_key", "fourth_key"); - Document doc = createDocument("fifth_key", "fifth_key"); - - if (!collection.hasIndex("key")) { - collection.createIndex("key", IndexOptions.indexOptions(IndexType.NonUnique)); - } - if (!collection.hasIndex("second_key")) { - collection.createIndex("second_key", IndexOptions.indexOptions(IndexType.NonUnique)); - } - - collection.insert(doc1, doc2); - collection.update(where("key").eq("key").and(where("second_key").eq("second_key")), - doc, UpdateOptions.updateOptions(true)); - - for (Document document : collection.find()) { - System.out.println(document); - } - } - - @Data - @AllArgsConstructor - @NoArgsConstructor - public static class CompatChild implements Mappable { - private Long childId; - private String lastName; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("childId", childId) - .put("lastName", lastName); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - childId = document.get("childId", Long.class); - lastName = document.get("lastName", String.class); - } - } - - @Data - @NoArgsConstructor - @AllArgsConstructor - @Indices({ - @Index(value = "synced", type = IndexType.NonUnique) - }) - public static class Receipt implements Mappable { - private Status status; - @Id - private String clientRef; - private Boolean synced; - private Long createdTimestamp = System.currentTimeMillis(); - - @Override - public Document write(NitriteMapper mapper) { - return createDocument("status", status) - .put("clientRef", clientRef) - .put("synced", synced) - .put("createdTimestamp", createdTimestamp); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - if (document != null) { - Object status = document.get("status"); - if (status instanceof Status) { - this.status = (Status) status; - } else { - this.status = Status.valueOf(status.toString()); - } - this.clientRef = document.get("clientRef", String.class); - this.synced = document.get("synced", Boolean.class); - this.createdTimestamp = document.get("createdTimestamp", Long.class); - } - } - public enum Status { - COMPLETED, - PREPARING, - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/Retry.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/Retry.java deleted file mode 100644 index 00e34e7ad..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/Retry.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.dizitart.no2.mapdb; - -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; - -/** - * @author Anindya Chatterjee - */ -public class Retry implements TestRule { - private final int retryCount; - - public Retry(int retryCount) { - this.retryCount = retryCount; - } - - public Statement apply(Statement base, Description description) { - return statement(base, description); - } - - private Statement statement(final Statement base, final Description description) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - Throwable caughtThrowable = null; - - // implement retry logic here - for (int i = 0; i < retryCount; i++) { - try { - base.evaluate(); - return; - } catch (Throwable t) { - caughtThrowable = t; - System.err.println(description.getDisplayName() + ": run " + (i + 1) + " failed"); - } - } - System.err.println(description.getDisplayName() + ": giving up after " + retryCount + " failures"); - throw caughtThrowable; - } - }; - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/SerializabilityTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/SerializabilityTest.java deleted file mode 100644 index 513ffebe7..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/SerializabilityTest.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb; - -import lombok.Data; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.exceptions.ValidationException; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.File; -import java.io.Serializable; - -import static org.dizitart.no2.mapdb.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.mapdb.TestUtil.createDb; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee - */ -public class SerializabilityTest { - private NitriteCollection collection; - private File dbFile; - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - dbFile = new File(getRandomTempDbFile()); - db = createDb(dbFile.getPath()); - collection = db.getCollection("test"); - } - - @After - public void tearDown() { - if (db != null && !db.isClosed()) { - db.close(); - } - - if (dbFile.exists()) { - boolean delete = dbFile.delete(); - assertTrue(delete); - } - } - - @Test(expected = ValidationException.class) - public void testSerializabilityValidation() { - for (int i = 0; i < 5; i++) { - Document doc = Document.createDocument(); - doc.put("key", i); - doc.put("data", new NotSerializableClass(Integer.toString(i))); - collection.insert(doc); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("Write " + i + " completed"); - } - } - - @Test - public void testSerializablity() { - for (int i = 0; i < 5; i++) { - Document doc = Document.createDocument(); - doc.put("key", i); - doc.put("data", new SerializableClass(Integer.toString(i))); - collection.insert(doc); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("Write " + i + " completed"); - } - } - - @Data - public static class NotSerializableClass { - private String myId; - - public NotSerializableClass(String myId) { - this.myId = myId; - } - } - - @Data - public static class SerializableClass implements Serializable { - private String myId; - - public SerializableClass(String myId) { - this.myId = myId; - } - } -} - - diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/StressTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/StressTest.java deleted file mode 100644 index 231da9839..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/StressTest.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb; - -import lombok.Data; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import uk.co.jemos.podam.api.PodamFactory; -import uk.co.jemos.podam.api.PodamFactoryImpl; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import java.util.concurrent.atomic.AtomicLong; - -import static org.dizitart.no2.mapdb.DbTestOperations.getRandomTempDbFile; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee - */ -public class StressTest { - private final String fileName = getRandomTempDbFile(); - private Nitrite db; - private NitriteCollection collection; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void before() { - MapDBModule storeModule = MapDBModule.withConfig() - .filePath(fileName) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(); - - collection = db.getCollection("test"); - System.out.println(fileName); - } - - @Test - public void testIssue41() { - collection.createIndex("number", IndexOptions.indexOptions(IndexType.NonUnique)); - collection.createIndex("name", IndexOptions.indexOptions(IndexType.NonUnique)); - collection.createIndex("counter", IndexOptions.indexOptions(IndexType.Unique)); - - Random random = new Random(); - AtomicLong counter = new AtomicLong(System.currentTimeMillis()); - PodamFactory factory = new PodamFactoryImpl(); - - long start = System.currentTimeMillis(); - for (int i = 0; i < 100000; i++) { - Document doc = Document.createDocument(); - doc.put("number", random.nextDouble()); - doc.put("name", factory.manufacturePojo(String.class)); - doc.put("counter", counter.getAndIncrement()); - collection.insert(doc); - if (i % 10000 == 0) { - System.out.println(i + " entries written"); - } - } - System.out.println("Records inserted in " + ((System.currentTimeMillis() - start) / (1000 * 60)) + " minutes"); - - if (db.hasUnsavedChanges()) { - db.commit(); - } - - start = System.currentTimeMillis(); - DocumentCursor cursor = collection.find(); - System.out.println("Size ->" + cursor.size()); - System.out.println("Records size calculated in " + ((System.currentTimeMillis() - start) / (1000)) + " seconds"); - - int i = 0; - start = System.currentTimeMillis(); - for (Document element : cursor) { - assertNotNull(element); - i++; - if (i % 10000 == 0) { - System.out.println(i + " entries processed"); - } - } - System.out.println("Iteration completed in " + ((System.currentTimeMillis() - start) / (1000)) + " seconds"); - } - - @After - public void clear() throws IOException { - if (db != null && !db.isClosed()) { - long start = System.currentTimeMillis(); - db.close(); - System.out.println("Time to compact and close - " + (System.currentTimeMillis() - start) / 1000 + " seconds"); - } - Files.delete(Paths.get(fileName)); - } - - @Test - public void testRepoPerformanceWithIndex() { - // warm-up - List items = getItems(PerfTestIndexed.class); - ObjectRepository repo = db.getRepository(PerfTestIndexed.class); - for (PerfTestIndexed item : items) { - assertNotNull(item); - repo.insert(item); - } - repo.remove(Filter.ALL); - repo.drop(); - - // actual calculation - repo = db.getRepository(PerfTestIndexed.class); - long start = System.currentTimeMillis(); - for (PerfTestIndexed item : items) { - repo.insert(item); - } - long diff = System.currentTimeMillis() - start; - System.out.println("Time take to insert 10000 indexed items - " + diff + "ms"); - - start = System.currentTimeMillis(); - repo.remove(Filter.ALL); - diff = System.currentTimeMillis() - start; - System.out.println("Time take to remove 10000 indexed items - " + diff + "ms"); - } - - @Test - public void testRepoPerformanceWithoutIndex() { - // warm-up - List items = getItems(PerfTest.class); - ObjectRepository repo = db.getRepository(PerfTest.class); - for (PerfTest item : items) { - assertNotNull(item); - repo.insert(item); - } - repo.remove(Filter.ALL); - repo.drop(); - - // actual calculation - repo = db.getRepository(PerfTest.class); - long start = System.currentTimeMillis(); - for (PerfTest item : items) { - repo.insert(item); - } - long diff = System.currentTimeMillis() - start; - System.out.println("Time take to insert 10000 non-indexed items - " + diff + "ms"); - - start = System.currentTimeMillis(); - repo.remove(Filter.ALL); - diff = System.currentTimeMillis() - start; - System.out.println("Time take to remove 10000 non-indexed items - " + diff + "ms"); - } - - private List getItems(Class type) { - PodamFactory generator = new PodamFactoryImpl(); - List items = new ArrayList<>(); - for (int i = 0; i < 10000; i++) { - items.add(generator.manufacturePojoWithFullData(type)); - } - assertEquals(items.size(), 10000); - return items; - } - - @Data - public static class PerfTest implements Mappable { - private String firstName; - private String lastName; - private Integer age; - private String text; - - @Override - public Document write(NitriteMapper mapper) { - Document document = Document.createDocument(); - document.put("firstName", firstName); - document.put("lastName", lastName); - document.put("age", age); - document.put("text", text); - return document; - } - - @Override - public void read(NitriteMapper mapper, Document document) { - this.firstName = (String) document.get("firstName"); - this.lastName = (String) document.get("lastName"); - this.age = (Integer) document.get("age"); - this.text = (String) document.get("text"); - } - } - - @Indices({ - @Index(value = "firstName", type = IndexType.NonUnique), - @Index(value = "age", type = IndexType.NonUnique), - @Index(value = "text", type = IndexType.Fulltext), - }) - private static class PerfTestIndexed extends PerfTest { - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/TestUtil.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/TestUtil.java deleted file mode 100644 index ec8eafc27..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/TestUtil.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2019-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb; - -import com.fasterxml.jackson.databind.JsonNode; -import lombok.extern.slf4j.Slf4j; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; - -import java.io.IOException; -import java.util.*; - -/** - * @author Anindya Chatterjee - */ -@Slf4j -public class TestUtil { - - /** - * Determines whether the supplied `iterable` is sorted. - * - * @param the type parameter - * @param iterable the iterable - * @param ascending a boolean value indicating whether to sort in ascending order - * @return the boolean value indicating if `iterable` is sorted or not. - */ - public static > boolean isSorted(Iterable iterable, boolean ascending) { - Iterator iterator = iterable.iterator(); - if (!iterator.hasNext()) { - return true; - } - T t = iterator.next(); - while (iterator.hasNext()) { - T t2 = iterator.next(); - if (ascending) { - if (t.compareTo(t2) > 0) { - return false; - } - } else { - if (t.compareTo(t2) < 0) { - return false; - } - } - t = t2; - } - return true; - } - - public static Nitrite createDb() { - MapDBModule storeModule = MapDBModule.withConfig() - .build(); - - return Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(); - } - - public static Nitrite createDb(String user, String password) { - MapDBModule storeModule = MapDBModule.withConfig() - .build(); - - return Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(user, password); - } - - public static Nitrite createDb(String filePath) { - MapDBModule storeModule = MapDBModule.withConfig() - .filePath(filePath) - .build(); - - return Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(); - } - - public static Nitrite createDb(String filePath, String user, String password) { - return Nitrite.builder() - .loadModule(new MapDBModule(filePath)) - .fieldSeparator(".") - .openOrCreate(user, password); - } - - private static Document loadDocument(JsonNode node) { - Map objectMap = new LinkedHashMap<>(); - Iterator> fields = node.fields(); - while (fields.hasNext()) { - Map.Entry entry = fields.next(); - String name = entry.getKey(); - JsonNode value = entry.getValue(); - Object object = loadObject(value); - objectMap.put(name, object); - } - - return Document.createDocument(objectMap); - } - - private static Object loadObject(JsonNode node) { - if (node == null) - return null; - try { - switch (node.getNodeType()) { - case ARRAY: - return loadArray(node); - case BINARY: - return node.binaryValue(); - case BOOLEAN: - return node.booleanValue(); - case MISSING: - case NULL: - return null; - case NUMBER: - return node.numberValue(); - case OBJECT: - case POJO: - return loadDocument(node); - case STRING: - return node.textValue(); - } - } catch (IOException e) { - return null; - } - return null; - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - private static List loadArray(JsonNode array) { - if (array.isArray()) { - List list = new ArrayList(); - Iterator iterator = array.elements(); - while (iterator.hasNext()) { - Object element = iterator.next(); - if (element instanceof JsonNode) { - list.add(loadObject((JsonNode) element)); - } else { - list.add(element); - } - } - return list; - } - return null; - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionDeleteNegativeTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionDeleteNegativeTest.java deleted file mode 100644 index d541d3523..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionDeleteNegativeTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.collection; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.mapdb.BaseCollectionTest; -import org.junit.Test; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionDeleteNegativeTest extends BaseCollectionTest { - @Test(expected = NitriteIOException.class) - public void testDrop() { - collection.drop(); - insert(); - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - } - - @Test(expected = FilterException.class) - public void testDeleteWithInvalidFilter() { - insert(); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - - WriteResult writeResult = collection.remove(where("lastName").gt(null)); - assertEquals(writeResult.getAffectedCount(), 0); - } - - @Test(expected = ValidationException.class) - public void testDeleteNullDocument() { - insert(); - - collection.remove((Document) null); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionDeleteTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionDeleteTest.java deleted file mode 100644 index 799c4d169..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionDeleteTest.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.collection; - -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapdb.BaseCollectionTest; -import org.junit.Test; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -public class CollectionDeleteTest extends BaseCollectionTest { - - @Test - public void testDelete() { - insert(); - - WriteResult writeResult = collection.remove(where("lastName").notEq(null)); - assertEquals(writeResult.getAffectedCount(), 3); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 0); - } - - @Test - public void testDeleteWithOptions() { - insert(); - - WriteResult writeResult = collection.remove(where("lastName").notEq(null), true); - assertEquals(writeResult.getAffectedCount(), 1); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 2); - } - - @Test - public void testDeleteWithNonMatchingFilter() { - insert(); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - - WriteResult writeResult = collection.remove(where("lastName").eq("a")); - assertEquals(writeResult.getAffectedCount(), 0); - } - - @Test - public void testDeleteInEmptyCollection() { - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 0); - - WriteResult writeResult = collection.remove(where("lastName").notEq(null)); - assertEquals(writeResult.getAffectedCount(), 0); - } - - @Test - public void testClear() { - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.Unique)); - insert(); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - assertTrue(collection.hasIndex("firstName")); - - boolean uniqueError = false; - try { - collection.insert(doc1); - } catch (Exception e) { - uniqueError = true; - } finally { - assertTrue(uniqueError); - } - - collection.remove(Filter.ALL); - - cursor = collection.find(); - assertEquals(cursor.size(), 0); - assertTrue(collection.hasIndex("firstName")); - - collection.insert(doc1); - cursor = collection.find(); - assertEquals(cursor.size(), 1); - assertTrue(collection.hasIndex("firstName")); - } - - @Test - public void testRemoveAll() { - insert(); - WriteResult writeResult = collection.remove((Filter) null); - assertEquals(writeResult.getAffectedCount(), 3); - } - - @Test - public void testRemoveDocument() { - insert(); - - WriteResult writeResult = collection.remove(where("firstName").eq("fn1")); - assertEquals(writeResult.getAffectedCount(), 1); - assertEquals(collection.size(), 2); - - writeResult = collection.remove(where("firstName").eq("fn2")); - assertEquals(writeResult.getAffectedCount(), 1); - assertEquals(collection.size(), 1); - - assertEquals(collection.find(where("firstName").eq("fn1")).size(), 0); - assertEquals(collection.find(where("firstName").eq("fn2")).size(), 0); - assertEquals(collection.find(where("firstName").eq("fn3")).size(), 1); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionFactoryTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionFactoryTest.java deleted file mode 100644 index 10002aa70..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionFactoryTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.collection; - -import org.dizitart.no2.NitriteConfig; -import org.dizitart.no2.collection.CollectionFactory; -import org.dizitart.no2.common.concurrent.LockService; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.mapdb.Retry; -import org.junit.Rule; -import org.junit.Test; - -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee - */ -public class CollectionFactoryTest { - - @Rule - public Retry retry = new Retry(3); - - @Test(expected = ValidationException.class) - public void testGetCollectionMapStoreNull() { - CollectionFactory factory = new CollectionFactory(new LockService()); - assertNotNull(factory); - - NitriteConfig config = new NitriteConfig(); - factory.getCollection(null, config, true); - } - - @Test(expected = ValidationException.class) - public void testGetCollectionContextNull() { - CollectionFactory factory = new CollectionFactory(new LockService()); - factory.getCollection("test", null, false); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionFindByIndexNegativeTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionFindByIndexNegativeTest.java deleted file mode 100644 index ab5a86e65..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionFindByIndexNegativeTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.collection; - -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapdb.BaseCollectionTest; -import org.junit.Test; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionFindByIndexNegativeTest extends BaseCollectionTest { - @Test(expected = FilterException.class) - public void testFindTextWithWildCardMultipleWord() { - insert(); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - - DocumentCursor cursor = collection.find(where("body").text("*ipsum dolor*")); - assertEquals(cursor.size(), 1); - } - - @Test(expected = FilterException.class) - public void testFindTextWithOnlyWildCard() { - insert(); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - - DocumentCursor cursor = collection.find(where("body").text("*")); - assertEquals(cursor.size(), 1); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionFindByIndexTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionFindByIndexTest.java deleted file mode 100644 index 42902951f..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionFindByIndexTest.java +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.collection; - -import com.github.javafaker.Faker; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapdb.BaseCollectionTest; -import org.junit.Test; - -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.mapdb.TestUtil.isSorted; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionFindByIndexTest extends BaseCollectionTest { - - @Test - public void testFindByUniqueIndex() throws ParseException { - insert(); - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.Unique)); - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("firstName").eq("fn10")); - assertEquals(cursor.size(), 0); - - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.Unique)); - cursor = collection.find(where("birthDay").gt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").gte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lte( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").lt( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").gt( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").gte( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .and(where("firstName").eq("fn1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12"))); - assertEquals(cursor.size(), 3); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1")).not()); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").eq((byte) 4)); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").lt(4)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("firstName").notIn("fn1", "fn2")); - assertEquals(cursor.size(), 1); - } - - @Test - public void testFindByNonUniqueIndex() throws ParseException { - insert(); - collection.createIndex("lastName", IndexOptions.indexOptions(IndexType.NonUnique)); - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.NonUnique)); - - DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("lastName").eq("ln20")); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").gt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").gte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lte( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").lt( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").gt( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").gte( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .and(where("firstName").eq("fn1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12"))); - assertEquals(cursor.size(), 3); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1")).not()); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").eq((byte) 4)); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").lt(4)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("firstName").notIn("fn1", "fn2")); - assertEquals(cursor.size(), 1); - } - - @Test - public void testFindByFullTextIndexAfterInsert() { - insert(); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("body")); - - DocumentCursor cursor = collection.find(where("body").text("Lorem")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("body").text("nosql")); - assertEquals(cursor.size(), 0); - - collection.dropIndex("body"); - boolean filterException = false; - try { - collection.find(where("body").text("Lorem")).toList(); - } catch (FilterException fe) { - filterException = true; - } finally { - assertTrue(filterException); - } - } - - @Test - public void testFindByFullTextIndexBeforeInsert() { - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("body")); - insert(); - - DocumentCursor cursor = collection.find(where("body").text("Lorem")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("body").text("quick brown")); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("body").text("nosql")); - assertEquals(cursor.size(), 0); - - collection.dropIndex("body"); - boolean filterException = false; - try { - collection.find(where("body").text("Lorem")).toList(); - } catch (FilterException fe) { - filterException = true; - } finally { - assertTrue(filterException); - } - } - - @Test - public void testFindByIndexSortAscending() { - insert(); - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.Unique)); - - DocumentCursor cursor = collection.find().sort("birthDay", SortOrder.Ascending); - assertEquals(cursor.size(), 3); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, true)); - } - - @Test - public void testFindByIndexSortDescending() { - insert(); - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.Unique)); - - DocumentCursor cursor = collection.find().sort("birthDay", SortOrder.Descending); - assertEquals(cursor.size(), 3); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, false)); - } - - @Test - public void testFindByIndexLimitAndSort() { - insert(); - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.Unique)); - - DocumentCursor cursor = collection.find(). - sort("birthDay", SortOrder.Descending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, false)); - - cursor = collection.find(). - sort("birthDay", SortOrder.Ascending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, true)); - - cursor = collection.find(). - sort("firstName", SortOrder.Ascending).skipLimit(0, 30); - assertEquals(cursor.size(), 3); - List nameList = new ArrayList<>(); - for (Document document : cursor) { - nameList.add(document.get("firstName", String.class)); - } - assertTrue(isSorted(nameList, true)); - } - - @Test - public void testFindAfterDroppedIndex() { - insert(); - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.Unique)); - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - - collection.dropIndex("firstName"); - cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - } - - @Test - public void testFindTextWithWildCard() { - insert(); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - - DocumentCursor cursor = collection.find(where("body").text("Lo")); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("body").text("Lo*")); - assertEquals(cursor.size(), 1); // Lorem - - cursor = collection.find(where("body").text("*rem")); - assertEquals(cursor.size(), 1); // lorem - - cursor = collection.find(where("body").text("*or*")); - assertEquals(cursor.size(), 2); - } - - @Test - public void testFindTextWithEmptyString() { - insert(); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - - DocumentCursor cursor = collection.find(where("body").text("")); - assertEquals(cursor.size(), 0); - } - - @Test - public void testFindWithOrIndexed() { - NitriteCollection collection = db.getCollection("testFindWithOrIndexed"); - Document doc1 = Document.createDocument("firstName", "John").put("lastName", "Doe"); - Document doc2 = Document.createDocument("firstName", "Jane").put("lastName", "Doe"); - Document doc3 = Document.createDocument("firstName", "Jonas").put("lastName", "Doe"); - Document doc4 = Document.createDocument("firstName", "Johan").put("lastName", "Day"); - - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.Unique)); - collection.createIndex("lastName", IndexOptions.indexOptions(IndexType.NonUnique)); - - collection.insert(doc1, doc2, doc3, doc4); - - DocumentCursor cursor = collection.find(where("firstName").eq("John").or(where("lastName").eq("Day"))); - assertEquals(cursor.size(), 2); - - List list = cursor.toList(); - assertEquals(list.size(), 2); - } - - @Test - public void testIssue45() { - NitriteCollection collection = db.getCollection("testIssue45"); - Faker faker = new Faker(); - String text1 = faker.lorem().paragraph() + " quick brown"; - String text2 = faker.lorem().paragraph() + " fox jump"; - String text3 = faker.lorem().paragraph() + " over lazy"; - String text4 = faker.lorem().paragraph() + " dog"; - - List list1 = Arrays.asList(text1, text2); - List list2 = Arrays.asList(text1, text2, text3); - List list3 = Arrays.asList(text2, text3); - List list4 = Arrays.asList(text1, text2, text3, text4); - - Document doc1 = Document.createDocument("firstName", "John").put("notes", list1); - Document doc2 = Document.createDocument("firstName", "Jane").put("notes", list2); - Document doc3 = Document.createDocument("firstName", "Jonas").put("notes", list3); - Document doc4 = Document.createDocument("firstName", "Johan").put("notes", list4); - - collection.createIndex("notes", IndexOptions.indexOptions(IndexType.Fulltext)); - collection.insert(doc1, doc2, doc3, doc4); - - DocumentCursor cursor = collection.find(where("notes").text("fox")); - assertEquals(cursor.size(), 4); - - cursor = collection.find(where("notes").text("dog")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("notes").text("lazy")); - assertEquals(cursor.size(), 3); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionFindNegativeTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionFindNegativeTest.java deleted file mode 100644 index 26b7eb507..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionFindNegativeTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.collection; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.mapdb.BaseCollectionTest; -import org.junit.Test; - -import java.util.Date; -import java.util.List; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionFindNegativeTest extends BaseCollectionTest { - @Test(expected = ValidationException.class) - public void testFindFilterInvalidIndex() { - insert(); - collection.find(where("data.9").eq(4)).toList(); - } - - @Test(expected = ValidationException.class) - public void testFindOptionsNegativeOffset() { - insert(); - collection.find().skipLimit(-1, 1); - } - - @Test(expected = ValidationException.class) - public void testFindOptionsNegativeSize() { - insert(); - collection.find().skipLimit(0, -1); - } - - public void testFindOptionsInvalidOffset() { - insert(); - assertEquals(collection.find().skipLimit(10, 1).size(), 0); - } - - @Test(expected = ValidationException.class) - public void testFindInvalidSort() { - insert(); - collection.find().sort("data", SortOrder.Descending).toList(); - } - - @Test(expected = FilterException.class) - public void testFindTextFilterNonIndexed() { - insert(); - collection.find(where("body").text("Lorem")).toList(); - } - - @Test(expected = FilterException.class) - public void testFindWithRegexInvalidValue() { - insert(); - DocumentCursor cursor = collection.find(where("birthDay").regex("hello")); - assertEquals(cursor.size(), 1); - } - - @Test(expected = ValidationException.class) - public void testInvalidProjection() { - insert(); - DocumentCursor cursor = collection.find(where("birthDay").lte(new Date())). - sort("firstName", SortOrder.Ascending).skipLimit(0, 3); - - Document projection = createDocument("firstName", null) - .put("lastName", "ln2"); - - cursor.project(projection); - } - - @Test(expected = UnsupportedOperationException.class) - public void testToListAdd() { - insert(); - DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); - List documents = cursor.toList(); - documents.add(createDocument()); - } - - @Test(expected = UnsupportedOperationException.class) - public void testToListRemove() { - insert(); - DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); - List documents = cursor.toList(); - documents.clear(); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionFindTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionFindTest.java deleted file mode 100644 index 69a772bab..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionFindTest.java +++ /dev/null @@ -1,851 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.collection; - -import com.google.common.collect.Lists; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.NullOrder; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.exceptions.IndexingException; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapdb.BaseCollectionTest; -import org.joda.time.DateTime; -import org.junit.Test; - -import java.text.Collator; -import java.text.ParseException; -import java.util.*; -import java.util.stream.Collectors; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.common.Constants.*; -import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.$; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.mapdb.TestUtil.isSorted; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.*; - -public class CollectionFindTest extends BaseCollectionTest { - - private static Document trimMeta(Document document) { - document.remove(DOC_ID); - document.remove(DOC_REVISION); - document.remove(DOC_MODIFIED); - document.remove(DOC_SOURCE); - return document; - } - - @Test - public void testFindAll() { - insert(); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - } - - @Test - public void testFindWithFilter() throws ParseException { - insert(); - - DocumentCursor cursor = collection.find(where("birthDay").gt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").gte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lte( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").lt( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").gt( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").gte( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .and(where("firstName").eq("fn1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12"))); - assertEquals(cursor.size(), 3); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1")).not()); - assertEquals(cursor.size(), 2); - - - cursor = collection.find(where("data.1").eq((byte) 4)); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").lt(4)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("firstName").notIn("fn1", "fn2")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(ALL.not()); - assertEquals(cursor.size(), 0); - } - - @Test - public void testFindWithSkipLimit() { - insert(); - - DocumentCursor cursor = collection.find().skipLimit(0, 1); - assertEquals(cursor.size(), 1); - - cursor = collection.find().skipLimit(1, 3); - assertEquals(cursor.size(), 2); - - cursor = collection.find().skipLimit(0, 30); - assertEquals(cursor.size(), 3); - - cursor = collection.find().skipLimit(2, 3); - assertEquals(cursor.size(), 1); - } - - @Test - public void testFindWithSkip() { - insert(); - - DocumentCursor cursor = collection.find().skip(0); - assertEquals(cursor.size(), 3); - - cursor = collection.find().skip(1); - assertEquals(cursor.size(), 2); - - cursor = collection.find().skip(30); - assertEquals(cursor.size(), 0); - - cursor = collection.find().skip(2); - assertEquals(cursor.size(), 1); - - boolean invalid = false; - try { - cursor = collection.find().skip(-1); - assertEquals(cursor.size(), 1); - } catch (ValidationException e) { - invalid = true; - } - assertTrue(invalid); - } - - @Test - public void testFindWithLimit() { - insert(); - - DocumentCursor cursor = collection.find().limit(0); - assertEquals(cursor.size(), 0); - - cursor = collection.find().limit(1); - assertEquals(cursor.size(), 1); - - boolean invalid = false; - try { - cursor = collection.find().limit(-1); - assertEquals(cursor.size(), 1); - } catch (ValidationException e) { - invalid = true; - } - assertTrue(invalid); - - cursor = collection.find().limit(30); - assertEquals(cursor.size(), 3); - } - - @Test - public void testFindSortAscending() { - insert(); - - DocumentCursor cursor = collection.find().sort("birthDay", SortOrder.Ascending); - assertEquals(cursor.size(), 3); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, true)); - } - - @Test - public void testFindSortDescending() { - insert(); - - DocumentCursor cursor = collection.find().sort("birthDay", SortOrder.Descending); - assertEquals(cursor.size(), 3); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, false)); - } - - @Test - public void testFindLimitAndSort() { - insert(); - - DocumentCursor cursor = collection.find(). - sort("birthDay", SortOrder.Descending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, false)); - - cursor = collection.find(). - sort("birthDay", SortOrder.Ascending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, true)); - - cursor = collection.find(). - sort("firstName", SortOrder.Ascending).skipLimit(0, 30); - assertEquals(cursor.size(), 3); - List nameList = new ArrayList<>(); - for (Document document : cursor) { - nameList.add(document.get("firstName", String.class)); - } - assertTrue(isSorted(nameList, true)); - } - - @Test - public void testFindSortOnNonExistingField() { - insert(); - DocumentCursor cursor = collection.find().sort("my-value", SortOrder.Descending); - assertEquals(cursor.size(), 3); - } - - @Test - public void testFindInvalidField() { - insert(); - DocumentCursor cursor = collection.find(where("myField").eq("myData")); - assertEquals(cursor.size(), 0); - } - - @Test - public void testFindInvalidFieldWithInvalidAccessor() { - insert(); - DocumentCursor cursor = collection.find(where("myField.0").eq("myData")); - assertEquals(cursor.size(), 0); - } - - @Test - public void testFindLimitAndSortInvalidField() { - insert(); - DocumentCursor cursor = collection.find(). - sort("birthDay2", SortOrder.Descending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - } - - @Test - public void testGetById() { - collection.insert(doc1); - NitriteId id = NitriteId.createId("1"); - Document document = collection.getById(id); - assertNull(document); - - document = collection.find().firstOrNull(); - - assertEquals(document.get(DOC_ID), document.getId().getIdValue()); - assertEquals(document.get("firstName"), "fn1"); - assertEquals(document.get("lastName"), "ln1"); - assertArrayEquals((byte[]) document.get("data"), new byte[]{1, 2, 3}); - assertEquals(document.get("body"), "a quick brown fox jump over the lazy dog"); - } - - @Test - public void testFindWithFilterAndOption() { - insert(); - DocumentCursor cursor = collection.find(where("birthDay").lte(new Date())). - sort("firstName", SortOrder.Ascending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - } - - @Test - public void testFindTextWithRegex() { - insert(); - DocumentCursor cursor = collection.find(where("body").regex("hello")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("body").regex("test")); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("body").regex("^hello$")); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("body").regex(".*")); - assertEquals(cursor.size(), 3); - } - - @Test - public void testProject() { - insert(); - DocumentCursor cursor = collection.find(where("birthDay").lte(new Date())). - sort("firstName", SortOrder.Ascending).skipLimit(0, 3); - int iteration = 0; - for (Document document : cursor) { - switch (iteration) { - case 0: - assertTrue(isSimilar(document, doc1, "firstName", "lastName", "birthDay", "data", "list", "body")); - break; - case 1: - assertTrue(isSimilar(document, doc2, "firstName", "lastName", "birthDay", "data", "list", "body")); - break; - case 2: - assertTrue(isSimilar(document, doc3, "firstName", "lastName", "birthDay", "data", "list", "body")); - break; - } - iteration++; - } - assertEquals(iteration, 3); - } - - @Test - public void testProjectWithCustomDocument() { - insert(); - DocumentCursor cursor = collection.find(where("birthDay").lte(new Date())). - sort("firstName", SortOrder.Ascending).skipLimit(0, 3); - - Document projection = createDocument("firstName", null) - .put("lastName", null); - - Iterable documents = cursor.project(projection); - int iteration = 0; - for (Document document : documents) { - assertTrue(document.containsKey("firstName")); - assertTrue(document.containsKey("lastName")); - - assertFalse(document.containsKey("_id")); - assertFalse(document.containsKey("birthDay")); - assertFalse(document.containsKey("data")); - assertFalse(document.containsKey("body")); - - switch (iteration) { - case 0: - assertEquals(document.get("firstName"), "fn1"); - assertEquals(document.get("lastName"), "ln1"); - break; - case 1: - assertEquals(document.get("firstName"), "fn2"); - assertEquals(document.get("lastName"), "ln2"); - break; - case 2: - assertEquals(document.get("firstName"), "fn3"); - assertEquals(document.get("lastName"), "ln2"); - break; - } - iteration++; - } - assertEquals(iteration, 3); - } - - @Test - public void testFindWithArrayEqual() { - insert(); - DocumentCursor ids = collection.find(where("data").eq(new byte[]{3, 4, 3})); - assertNotNull(ids); - assertEquals(ids.size(), 1); - } - - @Test - public void testFindWithArrayEqualFailForWrongCardinality() { - insert(); - DocumentCursor ids = collection.find(where("data").eq(new byte[]{4, 3, 3})); - assertNotNull(ids); - assertEquals(ids.size(), 0); - } - - @Test - public void testFindWithIterableEqual() { - insert(); - DocumentCursor ids = collection.find(where("list").eq(Lists.newArrayList("three", "four", "three"))); - assertNotNull(ids); - assertEquals(ids.size(), 1); - } - - @Test - public void testFindWithIterableEqualFailForWrongCardinality() { - insert(); - DocumentCursor ids = collection.find(where("list").eq(Lists.newArrayList("four", "three", "three"))); - assertNotNull(ids); - assertEquals(ids.size(), 0); - } - - @Test - public void testFindInArray() { - insert(); - DocumentCursor ids = collection.find(where("data").elemMatch($.gte(2).and($.lt(5)))); - assertNotNull(ids); - assertEquals(ids.size(), 3); - - ids = collection.find(where("data").elemMatch($.gt(2).or($.lte(5)))); - assertNotNull(ids); - assertEquals(ids.size(), 3); - - ids = collection.find(where("data").elemMatch($.gt(1).and($.lt(4)))); - assertNotNull(ids); - assertEquals(ids.size(), 2); - } - - @Test - public void testFindInList() { - insert(); - DocumentCursor ids = collection.find(where("list").elemMatch($.regex("three"))); - assertNotNull(ids); - assertEquals(ids.size(), 2); - - ids = collection.find(where("list").elemMatch($.regex("hello"))); - assertNotNull(ids); - assertEquals(ids.size(), 0); - - ids = collection.find(where("list").elemMatch($.regex("hello").not())); - assertNotNull(ids); - assertEquals(ids.size(), 2); - } - - @Test - public void testElemMatchFilter() { - Document doc1 = createDocument("productScores", new Document[]{ - createDocument("product", "abc").put("score", 10), - createDocument("product", "xyz").put("score", 5) - }).put("strArray", new String[]{"a", "b"}); - - Document doc2 = createDocument("productScores", new Document[]{ - createDocument("product", "abc").put("score", 8), - createDocument("product", "xyz").put("score", 7) - }).put("strArray", new String[]{"d", "e"}); - - Document doc3 = createDocument("productScores", new Document[]{ - createDocument("product", "abc").put("score", 7), - createDocument("product", "xyz").put("score", 8) - }).put("strArray", new String[]{"a", "f"}); - - NitriteCollection prodCollection = db.getCollection("prodScore"); - prodCollection.insert(doc1, doc2, doc3); - - List documentList = prodCollection.find(where("productScores") - .elemMatch(where("product").eq("xyz").and(where("score").gte(8)))).toList(); - - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").lte(8).not())).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("product").eq("xyz").or(where("score").gte(8)))).toList(); - assertEquals(documentList.size(), 3); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("product").eq("xyz"))).toList(); - assertEquals(documentList.size(), 3); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").gte(10))).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").gt(8))).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").lt(7))).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").lte(7))).toList(); - assertEquals(documentList.size(), 3); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").in(7, 8))).toList(); - assertEquals(documentList.size(), 2); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").notIn(7, 8))).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("product").regex("xyz"))).toList(); - assertEquals(documentList.size(), 3); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.eq("a"))).toList(); - assertEquals(documentList.size(), 2); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.eq("a").or($.eq("f").or($.eq("b"))).not())).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.gt("e"))).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.gte("e"))).toList(); - assertEquals(documentList.size(), 2); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.lte("b"))).toList(); - assertEquals(documentList.size(), 2); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.lt("a"))).toList(); - assertEquals(documentList.size(), 0); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.in("a", "f"))).toList(); - assertEquals(documentList.size(), 2); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.regex("a"))).toList(); - assertEquals(documentList.size(), 2); - - } - - @Test - public void testNotEqualFilter() { - Document document = createDocument("abc", "123"); - document.put("xyz", null); - - collection.insert(document); - DocumentCursor cursor = collection.find(where("abc").eq("123")); - assertEquals(cursor.size(), 1); - assertEquals(cursor.toList().size(), 1); - - cursor = collection.find(where("xyz").eq(null)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("abc").notEq(null)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("abc").notEq(null).and(where("xyz").eq(null))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("abc").eq(null).and(where("xyz").notEq(null))); - assertEquals(cursor.size(), 0); - - collection.remove(ALL); - - document = createDocument("field", "two"); - document.put(DOC_REVISION, 1482225343161L); - - collection.insert(document); - Document projection = collection.find( - where(DOC_REVISION).gte(1482225343160L) - .and(where(DOC_REVISION).lte(1482225343162L) - .and(where(DOC_REVISION).notEq(null)))) - .firstOrNull(); - - assertNull(projection); - } - - @Test - public void testFilterAll() { - DocumentCursor cursor = collection.find(ALL); - assertNotNull(cursor); - assertEquals(cursor.size(), 0); - - insert(); - cursor = collection.find(ALL); - assertNotNull(cursor); - assertEquals(cursor.size(), 3); - } - - @Test - public void testIssue72() { - NitriteCollection coll = db.getCollection("test"); - coll.createIndex("id", IndexOptions.indexOptions(IndexType.Unique)); - coll.createIndex("group", IndexOptions.indexOptions(IndexType.NonUnique)); - - coll.remove(ALL); - - Document doc = createDocument().put("id", "test-1").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - doc = createDocument().put("id", "test-2").put("group", "groupA").put("startTime", DateTime.now()); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - DocumentCursor cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending); - assertEquals(2, cursor.size()); - assertNull(cursor.toList().get(1).get("startTime")); - assertNotNull(cursor.toList().get(0).get("startTime")); - - cursor = coll.find(where("group").eq("groupA")).sort("startTime", SortOrder.Ascending); - assertEquals(2, cursor.size()); - assertNull(cursor.toList().get(0).get("startTime")); - assertNotNull(cursor.toList().get(1).get("startTime")); - } - - @Test - public void testIssue93() { - NitriteCollection coll = db.getCollection("orderByOnNullableColumn2"); - - coll.remove(ALL); - - Document doc = createDocument().put("id", "test-2").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - doc = createDocument().put("id", "test-1").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - DocumentCursor cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending); - assertEquals(2, cursor.size()); - } - - @Test - public void testNullOrderWithAllNull() { - NitriteCollection coll = db.getCollection("test"); - - coll.remove(ALL); - - Document doc = createDocument().put("id", "test-2").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - doc = createDocument().put("id", "test-1").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - DocumentCursor cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending); - assertEquals(2, cursor.size()); - - DocumentCursor cursor2 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.Default); - assertEquals(2, cursor2.size()); - - assertThat(cursor.toList(), is(cursor2.toList())); - - DocumentCursor cursor3 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.First); - assertEquals(2, cursor3.size()); - - assertThat(cursor.toList(), is(cursor3.toList())); - - DocumentCursor cursor4 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.Last); - assertEquals(2, cursor4.size()); - - assertThat(cursor.toList(), is(cursor4.toList())); - - DocumentCursor cursor5 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.Last); - assertEquals(2, cursor5.size()); - - assertThat(cursor.toList(), is(cursor5.toList())); - - DocumentCursor cursor6 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.First); - assertEquals(2, cursor6.size()); - - assertThat(cursor.toList(), is(cursor6.toList())); - - DocumentCursor cursor7 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.Default); - assertEquals(2, cursor7.size()); - - assertThat(cursor.toList(), is(cursor7.toList())); - } - - @Test - public void testNullOrder() { - NitriteCollection coll = db.getCollection("test"); - try { - coll.createIndex("startTime", IndexOptions.indexOptions(IndexType.NonUnique)); - } catch (IndexingException e) { - // ignore - } - - coll.remove(ALL); - - Document doc1 = createDocument().put("id", "test-1").put("group", "groupA"); - assertEquals(1, coll.insert(doc1).getAffectedCount()); - - Document doc2 = createDocument().put("id", "test-2").put("group", "groupA").put("startTime", DateTime.now()); - assertEquals(1, coll.insert(doc2).getAffectedCount()); - - Document doc3 = createDocument().put("id", "test-3").put("group", "groupA").put("startTime", DateTime.now().plusMinutes(1)); - assertEquals(1, coll.insert(doc3).getAffectedCount()); - - DocumentCursor cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc3, doc2, doc1), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.First); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc1, doc3, doc2), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.Default); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc3, doc2, doc1), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.Last); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc3, doc2, doc1), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.First); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc1, doc2, doc3), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.Default); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc1, doc2, doc3), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.Last); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc2, doc3, doc1), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - } - - @Test - public void testFindFilterInvalidAccessor() { - insert(); - DocumentCursor cursor = collection.find(where("lastName.name").eq("ln2")); - assertEquals(cursor.size(), 0); - } - - @Test - public void testIssue144() { - Document doc1 = createDocument().put("id", "test-1").put("fruit", "Apple"); - Document doc2 = createDocument().put("id", "test-2").put("fruit", "Ôrange"); - Document doc3 = createDocument().put("id", "test-3").put("fruit", "Pineapple"); - - NitriteCollection coll = db.getCollection("test"); - coll.insert(doc1, doc2, doc3); - - DocumentCursor cursor = coll.find().sort("fruit", SortOrder.Ascending, - Collator.getInstance(Locale.FRANCE)); - assertEquals(cursor.toList().get(1).get("fruit"), "Ôrange"); - } - - @Test - public void testIdSet() { - insert(); - DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("lastName").eq("ln1")); - assertEquals(cursor.size(), 1); - - Document byId = cursor.iterator().next(); - assertEquals(byId.get("lastName"), "ln1"); - } - - @Test - public void testCollectionField() { - Document document = createDocument("name", "John") - .put("tags", new Document[]{ - createDocument("type", "example").put("other", "value"), - createDocument("type", "another-example").put("other", "some-other-value") - }); - - NitriteCollection example = db.getCollection("example"); - example.insert(document); - - document = createDocument("name", "Jane") - .put("tags", new Document[]{ - createDocument("type", "example2").put("other", "value2"), - createDocument("type", "another-example2").put("other", "some-other-value2") - }); - example.insert(document); - - DocumentCursor cursor = example.find(where("tags").elemMatch(where("type").eq("example"))); - for (Document doc : cursor) { - assertNotNull(doc); - assertEquals(doc.get("name"), "John"); - } - } - - @Test - public void testBetweenFilter() { - Document doc1 = createDocument("age", 31).put("tag", "one"); - Document doc2 = createDocument("age", 32).put("tag", "two"); - Document doc3 = createDocument("age", 33).put("tag", "three"); - Document doc4 = createDocument("age", 34).put("tag", "four"); - Document doc5 = createDocument("age", 35).put("tag", "five"); - - NitriteCollection collection = db.getCollection("tag"); - collection.insert(doc1, doc2, doc3, doc4, doc5); - collection.createIndex("age", IndexOptions.indexOptions(IndexType.Unique)); - - DocumentCursor cursor = collection.find(where("age").between(31, 35)); - assertEquals(cursor.size(), 5); - - cursor = collection.find(where("age").between(31, 35, false)); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("age").between(31, 35, false, true)); - assertEquals(cursor.size(), 4); - - cursor = collection.find(where("age").between(31, 35, false).not()); - assertEquals(cursor.size(), 2); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionIndexNegativeTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionIndexNegativeTest.java deleted file mode 100644 index cad0fdc3b..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionIndexNegativeTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.collection; - -import org.dizitart.no2.exceptions.IndexingException; -import org.dizitart.no2.exceptions.UniqueConstraintException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapdb.BaseCollectionTest; -import org.junit.Test; - -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionIndexNegativeTest extends BaseCollectionTest { - - @Test(expected = UniqueConstraintException.class) - public void testCreateInvalidUniqueIndex() { - collection.createIndex("lastName", IndexOptions.indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("lastName")); - insert(); - } - - @Test(expected = UniqueConstraintException.class) - public void testCreateIndexOnArray() { - collection.createIndex("data", IndexOptions.indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("data")); - // data array field has repetition, so unique constraint exception - insert(); - } - - @Test - public void testCreateOnInvalidField() { - insert(); - collection.createIndex("my-value", IndexOptions.indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("my-value")); - } - - @Test(expected = IndexingException.class) - public void testCreateFullTextOnNonTextField() { - insert(); - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("birthDay")); - } - - @Test(expected = IndexingException.class) - public void testDropIndexOnNonIndexedField() { - collection.dropIndex("data"); - } - - @Test(expected = IndexingException.class) - public void testRebuildIndexInvalid() { - collection.rebuildIndex("unknown", true); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionIndexTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionIndexTest.java deleted file mode 100644 index 4a56c3cff..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionIndexTest.java +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.collection; - -import com.google.common.collect.Lists; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.IndexingException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexEntry; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapdb.BaseCollectionTest; -import org.junit.Test; - -import java.util.Collection; -import java.util.Random; -import java.util.concurrent.Callable; - -import static org.awaitility.Awaitility.await; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionIndexTest extends BaseCollectionTest { - - @Test - public void testCreateIndex() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("firstName")); - - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - assertTrue(collection.hasIndex("lastName")); - - collection.createIndex("body", indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("body")); - - collection.createIndex("birthDay", null); - assertTrue(collection.hasIndex("birthDay")); - - insert(); - } - - @Test - public void testListIndexes() { - assertEquals(collection.listIndices().size(), 0); - - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("firstName")); - - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - assertTrue(collection.hasIndex("lastName")); - - collection.createIndex("body", indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("body")); - - assertEquals(collection.listIndices().size(), 3); - } - - @Test - public void testDropIndex() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("firstName")); - - collection.dropIndex("firstName"); - assertFalse(collection.hasIndex("firstName")); - } - - @Test - public void testDropAllIndexes() { - collection.dropAllIndices(); - - testCreateIndex(); - assertEquals(collection.listIndices().size(), 4); - - collection.dropAllIndices(); - assertEquals(collection.listIndices().size(), 0); - } - - @Test - public void testHasIndex() { - assertFalse(collection.hasIndex("lastName")); - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - assertTrue(collection.hasIndex("lastName")); - - assertFalse(collection.hasIndex("body")); - collection.createIndex("body", indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("body")); - } - - @Test - public void testDeleteWithIndex() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("body", indexOptions(IndexType.Fulltext)); - - insert(); - - WriteResult result = collection.remove(where("firstName").eq("fn1")); - assertEquals(result.getAffectedCount(), 1); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 2); - - result = collection.remove(where("body").text("Lorem")); - assertEquals(result.getAffectedCount(), 1); - - cursor = collection.find(); - assertEquals(cursor.size(), 1); - } - - @Test - public void testCreateIndexAsync() { - insert(); - collection.createIndex("body", indexOptions(IndexType.Fulltext, true)); - assertTrue(collection.isIndexing("body")); - - await().until(bodyIndexingCompleted()); - } - - @Test - public void testRebuildIndex() { - collection.createIndex("body", indexOptions(IndexType.Fulltext, false)); - insert(); - Collection indices = collection.listIndices(); - for (IndexEntry idx : indices) { - collection.rebuildIndex(idx.getField(), false); - } - } - - @Test - public void testRebuildIndexAsync() { - collection.createIndex("body", indexOptions(IndexType.Fulltext, true)); - insert(); - await().until(bodyIndexingCompleted()); - - Collection indices = collection.listIndices(); - for (IndexEntry idx : indices) { - collection.rebuildIndex(idx.getField(), true); - await().until(bodyIndexingCompleted()); - } - } - - @Test - public void testRebuildIndexOnRunningIndex() { - collection.createIndex("body", indexOptions(IndexType.Fulltext, false)); - Collection indices = collection.listIndices(); - IndexEntry idx = indices.iterator().next(); - insert(); - collection.rebuildIndex(idx.getField(), true); - - boolean error = false; - try { - collection.rebuildIndex(idx.getField(), true); - } catch (IndexingException ie) { - error = true; - } finally { - assertTrue(error); - await().until(bodyIndexingCompleted()); - } - } - - private Callable bodyIndexingCompleted() { - return () -> !collection.isIndexing("body"); - } - - @Test - public void testNullValueInIndexedField() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("birthDay", indexOptions(IndexType.NonUnique)); - insert(); - - Document document = createDocument("firstName", null) - .put("lastName", "ln1") - .put("birthDay", null) - .put("data", new byte[]{1, 2, 3}) - .put("list", Lists.newArrayList("one", "two", "three")) - .put("body", "a quick brown fox jump over the lazy dog"); - - collection.insert(document); - } - - @Test - public void testDropAllAndCreateIndex() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("firstName")); - collection.dropAllIndices(); - assertFalse(collection.hasIndex("firstName")); - - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("firstName")); - - collection = db.getCollection("test"); - assertTrue(collection.hasIndex("firstName")); - } - - @Test - public void testIssue178() { - collection.dropAllIndices(); - collection.remove(Filter.ALL); - - Document doc1 = createDocument("field", 5); - Document doc2 = createDocument("field", 4.3); - Document doc3 = createDocument("field", 0.03); - Document doc4 = createDocument("field", 4); - Document doc5 = createDocument("field", 5.0); - - collection.insert(doc1, doc2, doc3, doc4, doc5); - - DocumentCursor cursor = collection.find(where("field").eq(5)); - assertEquals(cursor.size(), 1); - - collection.createIndex("field", indexOptions(IndexType.NonUnique)); - - cursor = collection.find(where("field").eq(5)); - assertEquals(cursor.size(), 1); - } - - @Test - public void testIndexEvent() { - NitriteCollection collection = db.getCollection("index-test"); - Random random = new Random(); - for (int i = 0; i < 10000; i++) { - Document document = createDocument("first", random.nextInt()) - .put("second", random.nextDouble()); - collection.insert(document); - } - - collection.subscribe(eventInfo -> { - switch (eventInfo.getEventType()) { - case Insert: - fail("wrong event Insert"); - break; - case Update: - fail("wrong event Update"); - break; - case Remove: - fail("wrong event Remove"); - break; - case IndexStart: - case IndexEnd: - break; - } - assertTrue(eventInfo.getItem() instanceof String); - System.out.println(eventInfo.getEventType() + " for field " + eventInfo.getItem()); - }); - - collection.createIndex("first", indexOptions(IndexType.NonUnique)); - assertEquals(collection.find().size(), 10000); - - collection.createIndex("second", indexOptions(IndexType.NonUnique)); - assertEquals(collection.find().size(), 10000); - } - - @Test - public void testIndexAndSearchOnNullValues() { - NitriteCollection collection = db.getCollection("index-on-null"); - collection.insert(createDocument("first", null).put("second", 123).put("third", new Integer[]{1, 2, null})); - collection.insert(createDocument("first", "abcd").put("second", 456).put("third", new int[]{3, 1})); - collection.insert(createDocument("first", "xyz").put("second", 789).put("third", null)); - - collection.createIndex("first", indexOptions(IndexType.Unique)); - assertEquals(collection.find(where("first").eq(null)).size(), 1); - - collection.createIndex("third", indexOptions(IndexType.NonUnique)); - assertEquals(collection.find(where("third").eq(null)).size(), 2); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionInsertNegativeTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionInsertNegativeTest.java deleted file mode 100644 index 5d455e93d..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionInsertNegativeTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.collection; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.UniqueConstraintException; -import org.dizitart.no2.mapdb.BaseCollectionTest; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionInsertNegativeTest extends BaseCollectionTest { - @Test(expected = UniqueConstraintException.class) - public void testMultipleInsert() { - WriteResult result = collection.insert(doc1, doc2, doc3); - assertEquals(result.getAffectedCount(), 3); - Document document = collection.find().firstOrNull(); - collection.insert(document); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionInsertTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionInsertTest.java deleted file mode 100644 index cbfdfa471..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionInsertTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.collection; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.mapdb.BaseCollectionTest; -import org.junit.Test; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.common.Constants.DOC_ID; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -public class CollectionInsertTest extends BaseCollectionTest { - - @Test - public void testInsert() { - WriteResult result = collection.insert(doc1, doc2, doc3); - assertEquals(result.getAffectedCount(), 3); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - - for (Document document : cursor) { - assertNotNull(document.get("firstName")); - assertNotNull(document.get("lastName")); - assertNotNull(document.get("birthDay")); - assertNotNull(document.get("data")); - assertNotNull(document.get("body")); - assertNotNull(document.get(DOC_ID)); - } - } - - @Test - public void testInsertHeteroDocs() { - Document document = createDocument("test", "Nitrite Test"); - - WriteResult result = collection.insert(doc1, doc2, doc3, document); - assertEquals(result.getAffectedCount(), 4); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionJoinTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionJoinTest.java deleted file mode 100644 index a2220b271..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionJoinTest.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.collection; - -import lombok.extern.slf4j.Slf4j; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.Lookup; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.mapdb.BaseCollectionTest; -import org.junit.Before; -import org.junit.Test; - -import java.util.Collection; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -@Slf4j -public class CollectionJoinTest extends BaseCollectionTest { - private NitriteCollection foreignCollection; - - @Before - @Override - public void setUp() { - try { - super.setUp(); - foreignCollection = db.getCollection("foreign"); - foreignCollection.remove(ALL); - - Document fdoc1 = createDocument("fName", "fn1") - .put("address", "ABCD Street") - .put("telephone", "123456789"); - - Document fdoc2 = createDocument("fName", "fn2") - .put("address", "XYZ Street") - .put("telephone", "000000000"); - - Document fdoc3 = createDocument("fName", "fn2") - .put("address", "Some other Street") - .put("telephone", "7893141321"); - - foreignCollection.insert(fdoc1, fdoc2, fdoc3); - } catch (Throwable t) { - log.error("Error while initializing test database", t); - } - } - - @Test - @SuppressWarnings("unchecked") - public void testJoinAll() { - insert(); - - Lookup lookup = new Lookup(); - lookup.setLocalField("firstName"); - lookup.setForeignField("fName"); - lookup.setTargetField("personalDetails"); - - RecordStream result = collection.find().join(foreignCollection.find(), lookup); - assertEquals(result.size(), 3); - - for (Document document : result) { - if (document.get("firstName") == "fn1") { - Collection personalDetails = (Collection) document.get("personalDetails"); - assertNotNull(personalDetails); - assertEquals(personalDetails.size(), 1); - Object[] details = personalDetails.toArray(); - assertEquals(((Document) details[0]).get("telephone"), "123456789"); - } else if (document.get("firstName") == "fn2") { - Collection personalDetails = (Collection) document.get("personalDetails"); - assertNotNull(personalDetails); - assertEquals(personalDetails.size(), 2); - Object[] details = personalDetails.toArray(); - for (Object o : details) { - Document d = (Document) o; - if (d.get("address").equals("XYZ Street")) { - assertEquals(d.get("telephone"), "000000000"); - } else { - assertEquals(d.get("telephone"), "7893141321"); - } - } - } else if (document.get("firstName") == "fn3") { - assertNull(document.get("personalDetails")); - } - System.out.println(document); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionUpdateTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionUpdateTest.java deleted file mode 100644 index 5691999cc..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/CollectionUpdateTest.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.collection; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.UpdateOptions; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.NotIdentifiableException; -import org.dizitart.no2.exceptions.UniqueConstraintException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapdb.BaseCollectionTest; -import org.junit.Test; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.*; - -public class CollectionUpdateTest extends BaseCollectionTest { - - @Test - public void testUpdate() { - insert(); - - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertEquals(document.get("lastName"), "ln1"); - } - - WriteResult updateResult = collection.update(where("firstName").eq("fn1"), - createDocument("lastName", "new-last-name")); - assertEquals(updateResult.getAffectedCount(), 1); - - cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertEquals(document.get("lastName"), "new-last-name"); - } - } - - @Test(expected = NotIdentifiableException.class) - public void testUpsertWithoutId() { - insert(); - Document update = createDocument("lastName", "ln4"); - WriteResult writeResult = collection.update(update, false); - assertEquals(writeResult.getAffectedCount(), 0); - assertEquals(collection.size(), 3); - } - - @Test - public void testUpsert() { - insert(); - assertEquals(collection.size(), 3); - - Document update = createDocument("lastName", "ln4"); - WriteResult writeResult = collection.update(update, true); - assertEquals(writeResult.getAffectedCount(), 1); - assertEquals(collection.size(), 4); - - Document document = collection.find(where("lastName").eq("ln4")) - .firstOrNull(); - assertTrue(isSimilar(document, update, "lastName")); - } - - @Test - public void testOptionUpsert() { - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - - WriteResult updateResult = collection.update(where("firstName").eq("fn1"), - doc1, UpdateOptions.updateOptions(true)); - assertEquals(updateResult.getAffectedCount(), 1); - - cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertTrue(isSimilar(document, doc1, "firstName", "lastName", "birthDay", "data", "list", "body")); - } - } - - @Test - public void testUpdateMultiple() { - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - - insert(); - - Document document = createDocument("lastName", "newLastName1"); - WriteResult updateResult = collection.update(where("firstName").eq("fn1").not(), - document); - assertEquals(updateResult.getAffectedCount(), 2); - - cursor = collection.find(where("lastName").eq("newLastName1")); - assertEquals(cursor.size(), 2); - } - - @Test - public void testUpdateWithOptionsUpsertFalse() { - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - - UpdateOptions updateOptions = new UpdateOptions(); - updateOptions.setInsertIfAbsent(false); - - WriteResult updateResult = collection.update(where("firstName").eq("fn1"), - doc1, updateOptions); - assertEquals(updateResult.getAffectedCount(), 0); - - cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - } - - @Test - public void testUpdateMultipleWithJustOnceFalse() { - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - - insert(); - - UpdateOptions updateOptions = new UpdateOptions(); - updateOptions.setJustOnce(false); - - Document document = createDocument("lastName", "newLastName1"); - WriteResult updateResult = collection.update(where("firstName").eq("fn1").not(), - document, updateOptions); - assertEquals(updateResult.getAffectedCount(), 2); - - cursor = collection.find(where("lastName").eq("newLastName1")); - assertEquals(cursor.size(), 2); - } - - @Test - public void testUpdateMultipleWithJustOnceTrue() { - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - - insert(); - - UpdateOptions updateOptions = new UpdateOptions(); - updateOptions.setJustOnce(true); - - Document document = createDocument("lastName", "newLastName1"); - collection.update(where("firstName").eq("fn1").not(), - document, updateOptions); - } - - @Test - public void testUpdateWithNewField() { - insert(); - - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertEquals(document.get("lastName"), "ln1"); - } - - WriteResult updateResult = collection.update(where("firstName").eq("fn1"), - createDocument("new-value", "new-value-value")); - assertEquals(updateResult.getAffectedCount(), 1); - - cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertEquals(document.get("new-value"), "new-value-value"); - } - } - - @Test - public void testUpdateInvalidFilter() { - insert(); - - DocumentCursor cursor = collection.find(where("lastName").eq("ln1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertEquals(document.get("firstName"), "fn1"); - } - - // to check if NitriteId is valid. - WriteResult updateResult = collection.update(where("some-value").eq("some-value"), - createDocument("lastName", "new-last-name")); - assertEquals(updateResult.getAffectedCount(), 0); - } - - @Test - public void updateAfterAttributeRemoval() { - NitriteCollection coll = db.getCollection("test_updateAfterAttributeRemoval"); - coll.remove(Filter.ALL); - - Document doc = createDocument().put("id", "test-1").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - Document savedDoc1 = coll.find().firstOrNull(); - assertNotNull(savedDoc1); - - Document clonedDoc1 = savedDoc1.clone(); - assertEquals(savedDoc1, clonedDoc1); - - clonedDoc1.put("group", null); -// clonedDoc1.remove("group"); - assertEquals(1, coll.update(clonedDoc1).getAffectedCount()); - - Document savedDoc2 = coll.find(Filter.ALL).firstOrNull(); - assertNotNull(savedDoc2); - assertNull(savedDoc2.get("group")); - } - - @Test(expected = NotIdentifiableException.class) - public void testUpdateWithoutId() { - NitriteCollection collection = db.getCollection("test"); - Document document = createDocument("test", "test123"); - collection.update(document); - } - - @Test(expected = NotIdentifiableException.class) - public void testRemoveWithoutId() { - NitriteCollection collection = db.getCollection("test"); - Document document = createDocument("test", "test123"); - collection.remove(document); - } - - @Test(expected = NitriteIOException.class) - public void testRegisterListenerAfterDrop() { - NitriteCollection collection = db.getCollection("test"); - collection.drop(); - collection.subscribe(changeInfo -> fail("should not happen")); - } - - @Test(expected = NitriteIOException.class) - public void testRegisterListenerAfterClose() { - NitriteCollection collection = db.getCollection("test"); - collection.close(); - collection.subscribe(changeInfo -> fail("should not happen")); - } - - @Test(expected = UniqueConstraintException.class) - public void testIssue151() { - Document doc1 = createDocument().put("id", "test-1").put("fruit", "Apple"); - Document doc2 = createDocument().put("id", "test-2").put("fruit", "Ôrange"); - NitriteCollection coll = db.getCollection("test"); - coll.insert(doc1, doc2); - - coll.createIndex("fruit", indexOptions(IndexType.Unique)); - - assertEquals(coll.find(where("fruit").eq("Apple")).size(), 1); - - Document doc3 = coll.find(where("id").eq("test-2")).firstOrNull(); - - doc3.put("fruit", "Apple"); - coll.update(doc3); - - assertEquals(coll.find(where("fruit").eq("Apple")).size(), 1); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/NitriteCollectionTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/NitriteCollectionTest.java deleted file mode 100644 index 16ddfcf9b..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/NitriteCollectionTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.collection; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.mapdb.Retry; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import static org.dizitart.no2.mapdb.TestUtil.createDb; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee - */ -public class NitriteCollectionTest { - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testAttributes() { - db = createDb(); - NitriteCollection collection = db.getCollection("test"); - - Attributes attributes = new Attributes("test"); - collection.setAttributes(attributes); - - assertEquals(collection.getAttributes(), attributes); - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/operation/DocumentCursorTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/operation/DocumentCursorTest.java deleted file mode 100644 index c4b02d4a3..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/operation/DocumentCursorTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.collection.operation; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.mapdb.Retry; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.util.Iterator; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.mapdb.TestUtil.createDb; -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee. - */ -public class DocumentCursorTest { - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testFindResult() { - db = createDb(); - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("first", "second")); - - DocumentCursor result = collection.find(); - assertNotNull(result); - } - - @Test(expected = InvalidOperationException.class) - public void testIteratorRemove() { - db = createDb(); - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("first", "second")); - - DocumentCursor cursor = collection.find(); - Iterator iterator = cursor.iterator(); - if (iterator.hasNext()) { - iterator.next(); - iterator.remove(); - } - } - - @Test - public void testValidateProjection() { - db = createDb(); - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("first", "second")); - - Document projection = createDocument("first", createDocument("second", null)); - RecordStream project = collection.find().project(projection); - assertNotNull(project); - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/operation/JoinedDocumentStreamTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/operation/JoinedDocumentStreamTest.java deleted file mode 100644 index 5fbb186c6..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/collection/operation/JoinedDocumentStreamTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.collection.operation; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.Lookup; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.mapdb.Retry; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.util.Iterator; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.mapdb.TestUtil.createDb; -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee - */ -public class JoinedDocumentStreamTest { - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testFindResult() { - db = createDb(); - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("first", "second")); - - RecordStream result = collection.find().join(collection.find(), new Lookup()); - assertNotNull(result); - } - - @Test(expected = InvalidOperationException.class) - public void testIteratorRemove() { - db = createDb(); - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("first", "second")); - - RecordStream cursor = collection.find().join(collection.find(), new Lookup()); - assertNotNull(cursor.toString()); - Iterator iterator = cursor.iterator(); - if (iterator.hasNext()) { - iterator.next(); - iterator.remove(); - } - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/common/event/EventTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/common/event/EventTest.java deleted file mode 100644 index 9098e1119..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/common/event/EventTest.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.common.event; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.collection.events.EventType; -import org.dizitart.no2.mapdb.MapDBModule; -import org.dizitart.no2.mapdb.MapDBModuleBuilder; -import org.dizitart.no2.mapdb.Retry; -import org.dizitart.no2.mapdb.repository.data.Employee; -import org.dizitart.no2.repository.ObjectRepository; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Collection; -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.awaitility.Awaitility.await; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.mapdb.DbTestOperations.getRandomTempDbFile; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -@RunWith(Parameterized.class) -public class EventTest { - @Parameterized.Parameter - public boolean inMemory = false; - @Parameterized.Parameter(value = 1) - public boolean isProtected = false; - - private final String fileName = getRandomTempDbFile(); - private Nitrite db; - private ObjectRepository employeeRepository; - private SampleListenerCollection listener; - - @Rule - public Retry retry = new Retry(3); - - @Parameterized.Parameters(name = "InMemory = {0}, Protected = {1}") - public static Collection data() { - return Arrays.asList(new Object[][]{ - {false, false}, - {false, true}, - {true, false}, - {true, true}, - }); - } - - @Before - public void setUp() { - MapDBModuleBuilder builder = MapDBModule.withConfig(); - - if (!inMemory) { - builder.filePath(fileName); - } - - MapDBModule storeModule = builder.build(); - NitriteBuilder nitriteBuilder = Nitrite.builder() - .fieldSeparator(".") - .loadModule(storeModule); - - if (isProtected) { - db = nitriteBuilder.openOrCreate("test-user", "test-password"); - } else { - db = nitriteBuilder.openOrCreate(); - } - - employeeRepository = db.getRepository(Employee.class); - listener = new SampleListenerCollection(); - employeeRepository.subscribe(listener); - } - - @Test - public void testInsert() { - Employee employee = new Employee(); - employee.setEmpId(1L); - employeeRepository.insert(employee); - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); - assertEquals(listener.getAction(), EventType.Insert); - assertNotNull(listener.getItem()); - } - - @Test - public void testUpdate() { - Employee e = new Employee(); - e.setEmpId(1L); - e.setAddress("abcd"); - employeeRepository.insert(e); - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); - assertEquals(listener.getAction(), EventType.Insert); - assertNotNull(listener.getItem()); - - e.setAddress("xyz"); - employeeRepository.update(where("empId").eq(1L), e); - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Update)); - assertEquals(listener.getAction(), EventType.Update); - assertNotNull(listener.getItem()); - - Employee byId = employeeRepository.getById(1L); - assertEquals(byId.getAddress(), "xyz"); - } - - @Test - public void testUpsert() { - Employee e = new Employee(); - e.setEmpId(1L); - e.setAddress("abcd"); - - employeeRepository.update(where("empId").eq(1), e, true); - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); - assertEquals(listener.getAction(), EventType.Insert); - assertNotNull(listener.getItem()); - } - - @Test - public void testDelete() { - Employee e = new Employee(); - e.setEmpId(1L); - e.setAddress("abcd"); - - employeeRepository.insert(e); - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); - - employeeRepository.remove(where("empId").eq(1L)); - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Remove)); - - System.out.println("Action - " + listener.getAction()); - assertEquals(listener.getAction(), EventType.Remove); - assertNotNull(listener.getItem()); - } - - @Test - public void testDrop() { - employeeRepository.drop(); - assertNull(listener.getItem()); - } - - @Test - public void testClose() { - if (employeeRepository.isOpen()) { - employeeRepository.close(); - } - assertNull(listener.getItem()); - } - - @Test - public void testDeregister() { - employeeRepository.unsubscribe(listener); - Employee e = new Employee(); - e.setEmpId(1L); - e.setAddress("abcd"); - - employeeRepository.insert(e); - assertNull(listener.getAction()); - assertNull(listener.getItem()); - } - - @Test - public void testMultipleListeners() { - final AtomicInteger count = new AtomicInteger(0); - employeeRepository.subscribe(changeInfo -> count.incrementAndGet()); - - employeeRepository.subscribe(changeInfo -> count.incrementAndGet()); - - Employee e = new Employee(); - e.setEmpId(1L); - e.setAddress("abcd"); - employeeRepository.insert(e); - - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); - assertEquals(count.get(), 2); - } - - @Test - public void testSingleEventListener() { - final AtomicInteger count = new AtomicInteger(0); - employeeRepository.subscribe(changeInfo -> count.incrementAndGet()); - - employeeRepository = db.getRepository(Employee.class); - Employee e = new Employee(); - e.setEmpId(1L); - e.setAddress("abcd"); - employeeRepository.insert(e); - - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); - assertEquals(count.get(), 1); - } - - @After - public void clear() throws IOException { - if (employeeRepository != null) { - if (!employeeRepository.isDropped() - && employeeRepository.isOpen()) { - employeeRepository.remove(ALL); - employeeRepository.unsubscribe(listener); - employeeRepository.close(); - } - } - - if (db != null) { - db.commit(); - db.close(); - } - - if (!inMemory) { - Files.delete(Paths.get(fileName)); - } - } - - private Callable listenerPrepared(final EventType action) { - return () -> listener.getAction() == action; - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/common/event/SampleListenerCollection.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/common/event/SampleListenerCollection.java deleted file mode 100644 index 1089753cf..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/common/event/SampleListenerCollection.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.common.event; - -import lombok.Getter; -import org.dizitart.no2.collection.events.CollectionEventInfo; -import org.dizitart.no2.collection.events.CollectionEventListener; -import org.dizitart.no2.collection.events.EventType; - -/** - * @author Anindya Chatterjee. - */ -@Getter -class SampleListenerCollection implements CollectionEventListener { - private EventType action; - private Object item; - - @Override - public void onEvent(CollectionEventInfo eventInfo) { - if (eventInfo != null) { - this.action = eventInfo.getEventType(); - this.item = eventInfo.getItem(); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/mapdb/NitriteMapStressTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/mapdb/NitriteMapStressTest.java deleted file mode 100644 index 023bda1f1..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/mapdb/NitriteMapStressTest.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2019-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.mapdb; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.mapdb.Retry; -import org.dizitart.no2.store.NitriteMap; -import org.dizitart.no2.store.NitriteStore; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.UUID; - -import static org.dizitart.no2.mapdb.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.mapdb.TestUtil.createDb; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee. - */ -public class NitriteMapStressTest { - private final String dbPath = getRandomTempDbFile(); - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testWithInsertReadUpdate() { - db = createDb(dbPath); - - NitriteStore nitriteStore = db.getStore(); - NitriteMap nitriteMap = nitriteStore.openMap("testWithInsertReadUpdate", - String.class, Document.class); - - int count = 10000; - for (int i = 0; i < count; i++) { - Document record = Document.createDocument(); - record.put("firstName", UUID.randomUUID().toString()); - record.put("failed", false); - record.put("lastName", UUID.randomUUID().toString()); - record.put("processed", false); - - nitriteMap.put(UUID.randomUUID().toString(), record); - } - - for (Pair entry : nitriteMap.entries()) { - String key = entry.getFirst(); - Document record = entry.getSecond(); - - record.put("processed", true); - - nitriteMap.put(key, record); - } - - db.close(); - } - - @Test - public void testNullKey() { - db = createDb(dbPath); - NitriteStore nitriteStore = db.getStore(); - NitriteMap nitriteMap = nitriteStore.openMap("testNullKey", - String.class, Document.class); - nitriteMap.put(null, Document.createDocument()); - - assertNotNull(nitriteMap.get(null)); - assertEquals(nitriteMap.size(), 1); - - nitriteMap.put(null, Document.createDocument("first", 1)); - assertNotNull(nitriteMap.get(null)); - assertEquals(nitriteMap.size(), 1); - } - - @Test(expected = ValidationException.class) - public void testNullValue() { - db = createDb(dbPath); - NitriteStore nitriteStore = db.getStore(); - NitriteMap nitriteMap = nitriteStore.openMap("testNullValue", - String.class, Document.class); - nitriteMap.put(null, null); - } - - @Test(expected = ValidationException.class) - public void testNullPutIfAbsent() { - db = createDb(dbPath); - NitriteStore nitriteStore = db.getStore(); - NitriteMap nitriteMap = nitriteStore.openMap("testNullPutIfAbsent", - String.class, Document.class); - nitriteMap.putIfAbsent(null, null); - } - - @After - public void tearDown() throws IOException { - if (db != null && !db.isClosed()) { - db.close(); - } - Files.delete(Paths.get(dbPath)); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/mapdb/NitriteStoreEventTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/mapdb/NitriteStoreEventTest.java deleted file mode 100644 index 9a0ed8a0c..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/mapdb/NitriteStoreEventTest.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2019-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.mapdb; - -import lombok.Data; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.mapdb.MapDBModule; -import org.dizitart.no2.mapdb.Retry; -import org.dizitart.no2.store.events.EventInfo; -import org.dizitart.no2.store.events.StoreEventListener; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.concurrent.TimeUnit; - -import static org.awaitility.Awaitility.await; -import static org.dizitart.no2.mapdb.DbTestOperations.getRandomTempDbFile; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee - */ -public class NitriteStoreEventTest { - private String dbFile; - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void before() { - dbFile = getRandomTempDbFile(); - } - - @After - public void cleanup() throws IOException { - if (db != null && !db.isClosed()) { - db.close(); - } - - if (Files.exists(Paths.get(dbFile))) { - Files.delete(Paths.get(dbFile)); - } - } - - @Test - public void testStoreEvents() { - TestStoreEventListener listener = new TestStoreEventListener(); - assertFalse(listener.opened); - assertFalse(listener.committed); - assertFalse(listener.closing); - assertFalse(listener.closed); - - MapDBModule module = MapDBModule.withConfig() - .filePath(dbFile) - .addStoreEventListener(listener) - .build(); - - db = Nitrite.builder() - .loadModule(module) - .fieldSeparator(".") - .openOrCreate(); - - await().atMost(1, TimeUnit.SECONDS).until(() -> listener.opened); - assertTrue(listener.opened); - assertFalse(listener.committed); - assertFalse(listener.closing); - assertFalse(listener.closed); - - db.commit(); - - await().atMost(1, TimeUnit.SECONDS).until(() -> listener.committed); - assertTrue(listener.opened); - assertTrue(listener.committed); - assertFalse(listener.closing); - assertFalse(listener.closed); - - db.close(); - - await().atMost(1, TimeUnit.SECONDS).until(() -> listener.closed); - assertTrue(listener.opened); - assertTrue(listener.committed); - assertTrue(listener.closing); - assertTrue(listener.closed); - - db.getStore().unsubscribe(listener); - } - - @Data - private static class TestStoreEventListener implements StoreEventListener { - private boolean opened; - private boolean committed; - private boolean closing; - private boolean closed; - - @Override - public void onEvent(EventInfo eventInfo) { - switch (eventInfo.getEvent()) { - case Opened: - opened = true; - break; - case Commit: - committed = true; - break; - case Closing: - closing = true; - break; - case Closed: - closed = true; - break; - } - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/migrate/MigrationTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/migrate/MigrationTest.java deleted file mode 100644 index ad1f00e27..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/migrate/MigrationTest.java +++ /dev/null @@ -1,557 +0,0 @@ -package org.dizitart.no2.mapdb.migrate; - -import com.github.javafaker.Faker; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.Constants; -import org.dizitart.no2.exceptions.MigrationException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapdb.MapDBModule; -import org.dizitart.no2.mapdb.Retry; -import org.dizitart.no2.migration.Instruction; -import org.dizitart.no2.migration.Migration; -import org.dizitart.no2.migration.TypeConverter; -import org.dizitart.no2.repository.ObjectRepository; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.UUID; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.mapdb.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.mapdb.TestUtil.createDb; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -public class MigrationTest { - private final String dbPath = getRandomTempDbFile(); - private Nitrite db; - private Faker faker; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - db = createDb(dbPath); - faker = new Faker(); - } - - @After - public void cleanUp() throws IOException { - if (!db.isClosed()) { - db.close(); - } - - Files.delete(Paths.get(dbPath)); - } - - @Test - public void testRepositoryMigrate() { - ObjectRepository oldRepo = db.getRepository(OldClass.class, "demo1"); - for (int i = 0; i < 10; i++) { - OldClass old = new OldClass(); - old.setEmpId(String.valueOf(faker.number().randomNumber())); - old.setFirstName(faker.name().firstName()); - old.setLastName(faker.name().lastName()); - old.setUuid(UUID.randomUUID().toString()); - - OldClass.Literature literature = new OldClass.Literature(); - literature.setRatings((float) faker.number().randomDouble(2, 1, 5)); - literature.setText(faker.lorem().paragraph()); - old.setLiterature(literature); - - oldRepo.insert(old); - } - - db.close(); - - Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { - @Override - public void migrate(Instruction instruction) { - instruction.forDatabase() - .addPassword("test-user", "test-password"); - - instruction.forRepository(OldClass.class, "demo1") - .renameRepository("new", null) - .changeDataType("empId", (TypeConverter) Long::parseLong) - .changeIdField("uuid", "empId") - .deleteField("uuid") - .renameField("lastName", "familyName") - .addField("fullName", document -> document.get("firstName", String.class) + " " - + document.get("familyName", String.class)) - .dropIndex("firstName") - .dropIndex("literature.text") - .changeDataType("literature.ratings", (TypeConverter) Math::round); - } - }; - - MapDBModule storeModule = MapDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate("test-user", "test-password"); - - ObjectRepository newRepo = db.getRepository(NewClass.class); - assertEquals(newRepo.size(), 10); - assertTrue(db.listCollectionNames().isEmpty()); - assertTrue(db.listKeyedRepository().isEmpty()); - - assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 2); - } - - @Test - public void testCollectionMigrate() { - NitriteCollection collection = db.getCollection("test"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - document.put("bloodGroup", faker.name().bloodGroup()); - document.put("age", faker.number().randomDigit()); - - collection.insert(document); - } - - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.NonUnique)); - collection.createIndex("bloodGroup", IndexOptions.indexOptions(IndexType.NonUnique)); - db.close(); - - Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { - @Override - public void migrate(Instruction instruction) { - instruction.forDatabase() - .addPassword("test-user", "test-password"); - - instruction.forCollection("test") - .rename("testCollectionMigrate") - .deleteField("lastName"); - } - }; - - MapDBModule storeModule = MapDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate("test-user", "test-password"); - - collection = db.getCollection("testCollectionMigrate"); - assertTrue(collection.hasIndex("firstName")); - assertEquals(collection.size(), 10); - assertEquals(db.listCollectionNames().size(), 1); - assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 2); - db.close(); - - migration = new Migration(2, 3) { - @Override - public void migrate(Instruction instruction) { - instruction.forDatabase() - .changePassword("test-user", "test-password", "password"); - - instruction.forCollection("testCollectionMigrate") - .dropIndex("firstName") - .deleteField("bloodGroup") - .addField("name", document -> faker.name().fullName()) - .addField("address") - .addField("vehicles", 1) - .renameField("age", "ageGroup") - .createIndex("ageGroup", IndexType.NonUnique); - } - }; - - storeModule = MapDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(3) - .addMigrations(migration) - .openOrCreate("test-user", "password"); - - collection = db.getCollection("testCollectionMigrate"); - assertEquals(collection.size(), 10); - assertEquals(db.listCollectionNames().size(), 1); - assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 3); - - assertFalse(collection.hasIndex("firstName")); - assertTrue(collection.hasIndex("ageGroup")); - assertEquals(collection.find(where("age").notEq(null)).size(), 0); - } - - @Test(expected = MigrationException.class) - public void testOpenWithoutSchemaVersion() { - NitriteCollection collection = db.getCollection("test"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("test") - .rename("testOpenWithoutSchemaVersion") - .deleteField("lastName"); - } - }; - - MapDBModule storeModule = MapDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testOpenWithoutSchemaVersion"); - assertEquals(collection.size(), 10); - db.close(); - - storeModule = MapDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(); - - collection = db.getCollection("testOpenWithoutSchemaVersion"); - assertEquals(collection.size(), 10); - } - - @Test - public void testDescendingSchema() { - NitriteCollection collection = db.getCollection("test"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("test") - .rename("testDescendingSchema") - .deleteField("lastName"); - } - }; - - MapDBModule storeModule = MapDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testDescendingSchema"); - assertEquals(collection.size(), 10); - db.close(); - - migration = new Migration(2, Constants.INITIAL_SCHEMA_VERSION) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("testDescendingSchema") - .rename("test"); - } - }; - - storeModule = MapDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(1) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - } - - @Test - public void testMigrationWithoutVersion() { - NitriteCollection collection = db.getCollection("test"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("test") - .rename("testMigrationWithoutVersion") - .deleteField("lastName"); - } - }; - - MapDBModule storeModule = MapDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testMigrationWithoutVersion"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - } - - @Test - public void testWrongSchemaVersionNoMigration() { - NitriteCollection collection = db.getCollection("testWrongSchemaVersionNoMigration"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration = new Migration(1, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("testWrongSchemaVersionNoMigration") - .rename("test") - .deleteField("lastName"); - } - }; - - MapDBModule storeModule = MapDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testWrongSchemaVersionNoMigration"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - - migration = new Migration(2, 3) { - @Override - public void migrate(Instruction instruction) { - instruction.forCollection("test") - .rename("testWrongSchemaVersionNoMigration"); - } - }; - - storeModule = MapDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testWrongSchemaVersionNoMigration"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - } - - @Test - public void testReOpenAfterMigration() { - NitriteCollection collection = db.getCollection("testReOpenAfterMigration"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration = new Migration(1, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("testReOpenAfterMigration") - .rename("test") - .deleteField("lastName"); - } - }; - - MapDBModule storeModule = MapDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testReOpenAfterMigration"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testReOpenAfterMigration"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .openOrCreate(); - - collection = db.getCollection("testReOpenAfterMigration"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - } - - @Test - public void testMultipleMigrations() { - NitriteCollection collection = db.getCollection("testMultipleMigrations"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration1 = new Migration(1, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("testMultipleMigrations") - .rename("test"); - } - }; - - Migration migration2 = new Migration(2, 3) { - @Override - public void migrate(Instruction instruction) { - instruction.forCollection("test") - .addField("fullName", "Dummy Name"); - } - }; - - MapDBModule storeModule = MapDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration1, migration2) - .openOrCreate(); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - assertEquals(collection.find(where("fullName").eq("Dummy Name")).size(), 0); - db.close(); - - Migration migration3 = new Migration(3, 4) { - @Override - public void migrate(Instruction instruction) { - instruction.forCollection("test") - .addField("age", 10); - } - }; - - storeModule = MapDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(4) - .addMigrations(migration1, migration2, migration3) - .openOrCreate(); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - assertEquals(collection.find(where("fullName").eq("Dummy Name")).size(), 10); - assertEquals(collection.find(where("age").eq(10)).size(), 10); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/migrate/NewClass.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/migrate/NewClass.java deleted file mode 100644 index db2ddddb8..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/migrate/NewClass.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.dizitart.no2.mapdb.migrate; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Entity; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; - -/** - * @author Anindya Chatterjee - */ -@Data -@Entity(value = "new", indices = { - @Index(value = "familyName", type = IndexType.NonUnique), - @Index(value = "fullName", type = IndexType.NonUnique), - @Index(value = "literature.ratings", type = IndexType.NonUnique), -}) -public class NewClass implements Mappable { - @Id - private Long empId; - private String firstName; - private String familyName; - private String fullName; - private Literature literature; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("empId", empId) - .put("firstName", firstName) - .put("familyName", familyName) - .put("fullName", fullName) - .put("literature", literature.write(mapper)); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - empId = document.get("empId", Long.class); - firstName = document.get("firstName", String.class); - familyName = document.get("familyName", String.class); - fullName = document.get("fullName", String.class); - - Document doc = document.get("literature", Document.class); - literature = new Literature(); - literature.read(mapper, doc); - } - - @Data - public static class Literature implements Mappable { - private String text; - private Integer ratings; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("text", text) - .put("ratings", ratings); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - text = document.get("text", String.class); - ratings = document.get("ratings", Integer.class); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/migrate/OldClass.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/migrate/OldClass.java deleted file mode 100644 index 2d2430488..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/migrate/OldClass.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.dizitart.no2.mapdb.migrate; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Entity; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; - -/** - * @author Anindya Chatterjee - */ -@Data -@Entity(value = "old", indices = { - @Index(value = "firstName", type = IndexType.NonUnique), - @Index(value = "lastName", type = IndexType.NonUnique), - @Index(value = "literature.text", type = IndexType.Fulltext), - @Index(value = "literature.ratings", type = IndexType.NonUnique), -}) -public class OldClass implements Mappable { - @Id - private String uuid; - private String empId; - private String firstName; - private String lastName; - private Literature literature; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("empId", empId) - .put("uuid", uuid) - .put("firstName", firstName) - .put("lastName", lastName) - .put("literature", literature.write(mapper)); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - empId = document.get("empId", String.class); - uuid = document.get("uuid", String.class); - firstName = document.get("firstName", String.class); - lastName = document.get("lastName", String.class); - - Document doc = document.get("literature", Document.class); - literature = new Literature(); - literature.read(mapper, doc); - } - - @Data - public static class Literature implements Mappable { - private String text; - private Float ratings; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("text", text) - .put("ratings", ratings); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - text = document.get("text", String.class); - ratings = document.get("ratings", Float.class); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/BaseObjectRepositoryTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/BaseObjectRepositoryTest.java deleted file mode 100644 index 4e33b4b13..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/BaseObjectRepositoryTest.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.mapdb.MapDBModule; -import org.dizitart.no2.mapdb.MapDBModuleBuilder; -import org.dizitart.no2.mapdb.Retry; -import org.dizitart.no2.mapdb.repository.data.*; -import org.dizitart.no2.repository.ObjectRepository; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Collection; - -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.mapdb.DbTestOperations.getRandomTempDbFile; - -@RunWith(value = Parameterized.class) -public abstract class BaseObjectRepositoryTest { - @Parameterized.Parameter - public boolean inMemory = false; - @Parameterized.Parameter(value = 1) - public boolean isProtected = false; - - protected Nitrite db; - ObjectRepository companyRepository; - ObjectRepository employeeRepository; - ObjectRepository aObjectRepository; - ObjectRepository cObjectRepository; - private final String fileName = getRandomTempDbFile(); - - @Rule - public Retry retry = new Retry(3); - - @Parameterized.Parameters(name = "InMemory = {0}, Protected = {1}") - public static Collection data() { - return Arrays.asList(new Object[][]{ - {false, false}, - {false, true}, - {true, false}, - {true, true}, - }); - } - - @Before - public void setUp() { - openDb(); - - companyRepository = db.getRepository(Company.class); - employeeRepository = db.getRepository(Employee.class); - - aObjectRepository = db.getRepository(ClassA.class); - cObjectRepository = db.getRepository(ClassC.class); - - for (int i = 0; i < 10; i++) { - Company company = DataGenerator.generateCompanyRecord(); - companyRepository.insert(company); - Employee employee = DataGenerator.generateEmployee(); - employee.setEmpId((long) i + 1); - employeeRepository.insert(employee); - - aObjectRepository.insert(ClassA.create(i + 50)); - cObjectRepository.insert(ClassC.create(i + 30)); - } - } - - private void openDb() { - MapDBModuleBuilder builder = MapDBModule.withConfig(); - - if (!inMemory) { - builder.filePath(fileName); - } - - MapDBModule storeModule = builder.build(); - NitriteBuilder nitriteBuilder = Nitrite.builder() - .fieldSeparator(".") - .loadModule(storeModule); - - if (isProtected) { - db = nitriteBuilder.openOrCreate("test-user", "test-password"); - } else { - db = nitriteBuilder.openOrCreate(); - } - } - - @After - public void clear() throws IOException { - if (companyRepository != null && !companyRepository.isDropped()) { - companyRepository.remove(ALL); - } - - if (employeeRepository != null && !employeeRepository.isDropped()) { - employeeRepository.remove(ALL); - } - - if (aObjectRepository != null && !aObjectRepository.isDropped()) { - aObjectRepository.remove(ALL); - } - - if (cObjectRepository != null && !cObjectRepository.isDropped()) { - cObjectRepository.remove(ALL); - } - - if (db != null && !db.isClosed()) { - db.commit(); - db.close(); - } - - if (!inMemory) { - Files.delete(Paths.get(fileName)); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/CustomFieldSeparatorTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/CustomFieldSeparatorTest.java deleted file mode 100644 index 5dc484871..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/CustomFieldSeparatorTest.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteConfig; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapdb.MapDBModule; -import org.dizitart.no2.mapdb.Retry; -import org.dizitart.no2.mapdb.repository.data.Company; -import org.dizitart.no2.mapdb.repository.data.Note; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.Serializable; -import java.util.Date; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee - */ -public class CustomFieldSeparatorTest { - private Nitrite db; - private ObjectRepository repository; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - MapDBModule module = MapDBModule.withConfig() - .build(); - - db = Nitrite.builder() - .loadModule(module) - .fieldSeparator(":") - .openOrCreate(); - - repository = db.getRepository(EmployeeForCustomSeparator.class); - } - - @After - public void reset() { - (new NitriteConfig()).fieldSeparator("."); - if (db != null && !db.isClosed()) { - db.close(); - } - } - - @Test - public void testFieldSeparator() { - assertEquals(NitriteConfig.getFieldSeparator(), ":"); - } - - @Test - public void testFindByEmbeddedField() { - EmployeeForCustomSeparator employee = new EmployeeForCustomSeparator(); - employee.setCompany(new Company()); - employee.setEmployeeNote(new Note()); - - employee.setEmpId(123L); - employee.setJoinDate(new Date()); - employee.setBlob(new byte[0]); - employee.setAddress("Dummy address"); - - employee.getCompany().setCompanyId(987L); - employee.getCompany().setCompanyName("Dummy Company"); - employee.getCompany().setDateCreated(new Date()); - - employee.getEmployeeNote().setNoteId(567L); - employee.getEmployeeNote().setText("Dummy Note"); - - repository.insert(employee); - - assertEquals(repository.find(where("employeeNote.text").eq("Dummy Note")).size(), 0); - assertEquals(repository.find(where("employeeNote:text").text("Dummy Note")).size(), 1); - - assertEquals(repository.find(where("company.companyName").eq("Dummy Company")).size(), 0); - assertEquals(repository.find(where("company:companyName").eq("Dummy Company")).size(), 1); - } - - @ToString - @EqualsAndHashCode - @Indices({ - @Index(value = "joinDate", type = IndexType.NonUnique), - @Index(value = "address", type = IndexType.Fulltext), - @Index(value = "employeeNote:text", type = IndexType.Fulltext) - }) - public static class EmployeeForCustomSeparator implements Serializable, Mappable { - @Id - @Getter - @Setter - private Long empId; - - @Getter - @Setter - private Date joinDate; - - @Getter - @Setter - private String address; - - @Getter - @Setter - private Company company; - - @Getter - @Setter - private byte[] blob; - - @Getter - @Setter - private Note employeeNote; - - EmployeeForCustomSeparator() { - } - - public EmployeeForCustomSeparator(EmployeeForCustomSeparator copy) { - empId = copy.empId; - joinDate = copy.joinDate; - address = copy.address; - company = copy.company; - blob = copy.blob; - employeeNote = copy.employeeNote; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument().put("empId", empId) - .put("joinDate", joinDate) - .put("address", address) - .put("blob", blob) - .put("company", company.write(mapper)) - .put("employeeNote", employeeNote.write(mapper)); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - empId = document.get("empId", Long.class); - joinDate = document.get("joinDate", Date.class); - address = document.get("address", String.class); - blob = document.get("blob", byte[].class); - employeeNote = new Note(); - Document doc = document.get("employeeNote", Document.class); - employeeNote.read(mapper, doc); - company = new Company(); - doc = document.get("company", Document.class); - company.read(mapper, doc); - } - } - -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/InternalClass.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/InternalClass.java deleted file mode 100644 index eb340f272..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/InternalClass.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Data -class InternalClass implements Mappable { - @Id - private long id; - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("id", id) - .put("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Long.class); - name = document.get("name", String.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/NitriteIdAsIdTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/NitriteIdAsIdTest.java deleted file mode 100644 index 994e24b93..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/NitriteIdAsIdTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.common.util.Iterables; -import org.dizitart.no2.exceptions.InvalidIdException; -import org.dizitart.no2.mapdb.Retry; -import org.dizitart.no2.mapdb.TestUtil; -import org.dizitart.no2.mapdb.repository.data.WithNitriteId; -import org.dizitart.no2.repository.Cursor; -import org.dizitart.no2.repository.ObjectRepository; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; - -import static org.dizitart.no2.mapdb.DbTestOperations.getRandomTempDbFile; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee - */ -public class NitriteIdAsIdTest { - private final String fileName = getRandomTempDbFile(); - private Nitrite db; - private ObjectRepository repo; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void before() { - db = TestUtil.createDb(fileName); - repo = db.getRepository(WithNitriteId.class); - } - - @After - public void after() throws IOException { - db.close(); - Files.delete(Paths.get(fileName)); - } - - @Test - public void testNitriteIdField() { - WithNitriteId item1 = new WithNitriteId(); - item1.name = "first"; - - WithNitriteId item2 = new WithNitriteId(); - item2.name = "second"; - - repo.insert(item1, item2); - - Cursor cursor = repo.find(); - for (WithNitriteId withNitriteId : cursor) { - System.out.println(withNitriteId.name); - assertNotNull(withNitriteId.idField); - } - - WithNitriteId withNitriteId = cursor.firstOrNull(); - withNitriteId.name = "third"; - - NitriteId id = withNitriteId.idField; - repo.update(withNitriteId); - - WithNitriteId byId = repo.getById(id); - assertEquals(withNitriteId, byId); - assertEquals(repo.size(), 2); - } - - @Test(expected = InvalidIdException.class) - public void setIdDuringInsert() { - WithNitriteId item1 = new WithNitriteId(); - item1.name = "first"; - item1.idField = NitriteId.newId(); - - repo.insert(item1); - } - - @Test - public void changeIdDuringUpdate() { - WithNitriteId item2 = new WithNitriteId(); - item2.name = "second"; - WriteResult result = repo.insert(item2); - NitriteId nitriteId = Iterables.firstOrNull(result); - WithNitriteId byId = repo.getById(nitriteId); - byId.idField = NitriteId.newId(); - - result = repo.update(byId); - assertEquals(result.getAffectedCount(), 0); - assertEquals(repo.size(), 1); - } - -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/ObjectCursorTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/ObjectCursorTest.java deleted file mode 100644 index 73a652dce..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/ObjectCursorTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository; - -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.mapdb.repository.data.Employee; -import org.dizitart.no2.repository.Cursor; -import org.junit.Test; - -import java.util.AbstractCollection; - -/** - * @author Anindya Chatterjee - */ -public class ObjectCursorTest extends BaseObjectRepositoryTest { - - @Test(expected = ValidationException.class) - public void testProjectForInterface() { - Cursor cursor = employeeRepository.find(); - cursor.project(Comparable.class); - } - - @Test(expected = ValidationException.class) - public void testProjectForPrimitive() { - Cursor cursor = employeeRepository.find(); - cursor.project(int.class); - } - - @Test(expected = ValidationException.class) - public void testProjectForArray() { - Cursor cursor = employeeRepository.find(); - cursor.project(String[].class); - } - - @Test(expected = ValidationException.class) - public void testProjectForAbstractClass() { - Cursor cursor = employeeRepository.find(); - cursor.project(AbstractCollection.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/ObjectRepositoryNegativeTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/ObjectRepositoryNegativeTest.java deleted file mode 100644 index 968d9bd97..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/ObjectRepositoryNegativeTest.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.*; -import org.dizitart.no2.mapdb.Retry; -import org.dizitart.no2.mapdb.TestUtil; -import org.dizitart.no2.mapdb.repository.data.*; -import org.dizitart.no2.repository.ObjectRepository; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; - -import static org.dizitart.no2.mapdb.DbTestOperations.getRandomTempDbFile; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class ObjectRepositoryNegativeTest { - private final String dbPath = getRandomTempDbFile(); - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - db = TestUtil.createDb(dbPath); - } - - @After - public void close() throws IOException { - db.close(); - db = null; - Files.delete(Paths.get(dbPath)); - } - - @Test(expected = ObjectMappingException.class) - public void testWithCircularReference() { - ObjectRepository repository = db.getRepository(WithCircularReference.class); - - WithCircularReference parent = new WithCircularReference(); - parent.setName("parent"); - WithCircularReference object = new WithCircularReference(); - object.setName("test"); - object.setParent(parent); - // circular reference - parent.setParent(object); - - WriteResult result = repository.insert(object); - for (NitriteId id : result) { - WithCircularReference instance = repository.getById(id); - assertEquals(instance.getName(), object.getName()); - assertEquals(instance.getParent().getName(), object.getParent().getName()); - } - } - - @Test(expected = ObjectMappingException.class) - public void testWithCustomConstructor() { - ObjectRepository repository = db.getRepository(WithCustomConstructor.class); - - WithCustomConstructor object = new WithCustomConstructor("test", 2L); - - WriteResult result = repository.insert(object); - for (NitriteId id : result) { - WithCustomConstructor instance = repository.getById(id); - assertEquals(object.getName(), instance.getName()); - assertEquals(object.getNumber(), instance.getNumber()); - } - } - - @Test(expected = InvalidIdException.class) - public void testWithEmptyStringId() { - ObjectRepository repository = db.getRepository(WithEmptyStringId.class); - WithEmptyStringId object = new WithEmptyStringId(); - object.setName(""); // empty id value - - WriteResult result = repository.insert(object); - for (NitriteId id : result) { - WithEmptyStringId instance = repository.getById(id); - assertEquals(instance, object); - } - } - - @Test(expected = InvalidIdException.class) - public void testWithNullId() { - ObjectRepository repository = db.getRepository(WithNullId.class); - WithNullId object = new WithNullId(); - - WriteResult result = repository.insert(object); - for (NitriteId id : result) { - WithNullId instance = repository.getById(id); - assertEquals(instance, object); - } - } - - @Test(expected = ValidationException.class) - public void testWithValueTypeRepository() { - ObjectRepository repository = db.getRepository(String.class); - repository.insert("test"); - } - - @Test(expected = InvalidOperationException.class) - public void testFindResultRemove() { - ObjectRepository repository = db.getRepository(Employee.class); - repository.insert(DataGenerator.generateEmployee()); - RecordStream result = repository.find(); - result.iterator().remove(); - } - - @Test(expected = InvalidOperationException.class) - public void testWithObjectId() { - ObjectRepository repository = db.getRepository(WithObjectId.class); - WithOutId id = new WithOutId(); - id.setName("test"); - id.setNumber(1); - - WithObjectId object = new WithObjectId(); - object.setWithOutId(id); - repository.insert(object); - } - - @Test(expected = NotIdentifiableException.class) - public void testUpdateNoId() { - ObjectRepository repository = db.getRepository(WithOutId.class); - WithOutId object = new WithOutId(); - object.setName("name"); - object.setNumber(1L); - repository.update(object); - } - - @Test(expected = NotIdentifiableException.class) - public void testRemoveNoId() { - ObjectRepository repository = db.getRepository(WithOutId.class); - WithOutId object = new WithOutId(); - object.setName("name"); - object.setNumber(1L); - repository.remove(object); - } - - @Test(expected = ValidationException.class) - public void testProjectionFailedInstantiate() { - ObjectRepository repository = db.getRepository(WithOutId.class); - WithOutId object = new WithOutId(); - object.setName("name"); - object.setNumber(1L); - repository.insert(object); - - RecordStream project = repository.find().project(NitriteId.class); - assertNull(project.toList()); - } - - @Test(expected = ValidationException.class) - public void testNullInsert() { - ObjectRepository repository = db.getRepository(WithOutId.class); - repository.insert(null); - } - - @Test(expected = InvalidIdException.class) - public void testGetByNullId() { - ObjectRepository repository = db.getRepository(WithPublicField.class); - WithPublicField object = new WithPublicField(); - object.name = "test"; - object.number = 2; - - repository.insert(object); - WithPublicField instance = repository.getById(null); - assertEquals(object.name, instance.name); - assertEquals(object.number, instance.number); - } - - @Test - public void testExternalNitriteId() { - ObjectRepository repository = db.getRepository(WithNitriteId.class); - WithNitriteId obj = new WithNitriteId(); - NitriteId id = NitriteId.createId("1"); - obj.setIdField(id); - obj.setName("testExternalNitriteId"); - WriteResult result = repository.update(obj, true); - - obj = new WithNitriteId(); - id = result.iterator().next(); - obj.setIdField(id); - obj.setName("testExternalNitriteId"); - result = repository.update(obj, true); - assertNotEquals(id.getIdValue(), result.iterator().next().getIdValue()); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/ObjectRepositoryTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/ObjectRepositoryTest.java deleted file mode 100644 index ed786e7df..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/ObjectRepositoryTest.java +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository; - -import com.github.javafaker.Faker; -import lombok.Data; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapdb.MapDBModule; -import org.dizitart.no2.mapdb.Retry; -import org.dizitart.no2.mapdb.repository.data.*; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.MappableMapper; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.Cursor; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Entity; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Date; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.awaitility.Awaitility.await; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.mapdb.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.module.NitriteModule.module; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class ObjectRepositoryTest { - private final String dbPath = getRandomTempDbFile(); - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - NitriteMapper mapper = new MappableMapper(); - MapDBModule storeModule = MapDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(module(mapper)) - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(); - } - - @After - public void close() throws IOException { - db.close(); - db = null; - Files.delete(Paths.get(dbPath)); - } - - @Test - public void testWithClassField() { - ObjectRepository repository = db.getRepository(WithClassField.class); - - WithClassField object = new WithClassField(); - object.setName("test"); - object.setClazz(String.class); - - repository.insert(object); - WithClassField instance = repository.getById("test"); - assertEquals(instance.getName(), object.getName()); - assertEquals(instance.getClazz(), object.getClazz()); - } - - @Test - public void testWithFinalField() { - ObjectRepository repository = db.getRepository(WithFinalField.class); - WithFinalField object = new WithFinalField(); - object.setName("test"); - - repository.insert(object); - for (WithFinalField instance : repository.find()) { - assertEquals(object.getName(), instance.getName()); - assertEquals(object.getNumber(), instance.getNumber()); - } - } - - @Test - public void testWithOutGetterSetter() { - ObjectRepository repository = db.getRepository(WithOutGetterSetter.class); - WithOutGetterSetter object = new WithOutGetterSetter(); - - repository.insert(object); - for (WithOutGetterSetter instance : repository.find()) { - assertEquals(object, instance); - } - } - - @Test - public void testWithOutId() { - ObjectRepository repository = db.getRepository(WithOutId.class); - WithOutId object = new WithOutId(); - object.setName("test"); - object.setNumber(2); - - repository.insert(object); - for (WithOutId instance : repository.find()) { - assertEquals(object.getName(), instance.getName()); - assertEquals(object.getNumber(), instance.getNumber()); - } - } - - @Test - public void testWithPublicField() { - ObjectRepository repository = db.getRepository(WithPublicField.class); - WithPublicField object = new WithPublicField(); - object.name = "test"; - object.number = 2; - - repository.insert(object); - WithPublicField instance = repository.getById("test"); - assertEquals(object.name, instance.name); - assertEquals(object.number, instance.number); - } - - @Test - public void testWithTransientField() { - ObjectRepository repository = db.getRepository(WithTransientField.class); - WithTransientField object = new WithTransientField(); - object.setNumber(2); - object.setName("test"); - - repository.insert(object); - WithTransientField instance = repository.getById(2L); - assertNotEquals(object.getName(), instance.getName()); - assertNull(instance.getName()); - assertEquals(object.getNumber(), instance.getNumber()); - } - - @Test - public void testWriteThousandRecords() { - int count = 1000; - - ObjectRepository repository = db.getRepository(StressRecord.class); - - for (int i = 0; i < count; i++) { - StressRecord record = new StressRecord(); - record.setFirstName(UUID.randomUUID().toString()); - record.setFailed(false); - record.setLastName(UUID.randomUUID().toString()); - record.setProcessed(false); - - repository.insert(record); - } - - Cursor cursor - = repository.find(where("failed").eq(false)); - for (StressRecord record : cursor) { - record.setProcessed(true); - repository.update(where("firstName").eq(record.getFirstName()), record); - } - } - - @Test - public void testWithPackagePrivateClass() { - ObjectRepository repository = db.getRepository(InternalClass.class); - InternalClass internalClass = new InternalClass(); - internalClass.setId(1); - internalClass.setName("name"); - - repository.insert(internalClass); - InternalClass instance = repository.getById((long) 1); - assertEquals(internalClass.getName(), instance.getName()); - assertEquals(internalClass.getId(), instance.getId()); - } - - @Test - public void testWithPrivateConstructor() { - ObjectRepository repository = - db.getRepository(WithPrivateConstructor.class); - - WithPrivateConstructor object = WithPrivateConstructor.create("test", 2L); - repository.insert(object); - for (WithPrivateConstructor instance : repository.find()) { - assertEquals(object, instance); - } - } - - @Test - public void testWithDateAsId() { - ObjectRepository repository = db.getRepository(WithDateId.class); - - WithDateId object1 = new WithDateId(); - object1.setId(new Date(1482773634L)); - object1.setName("first date"); - repository.insert(object1); - - WithDateId object2 = new WithDateId(); - object2.setName("second date"); - object2.setId(new Date(1482773720L)); - repository.insert(object2); - - assertEquals(repository.find(where("id").eq(new Date(1482773634L))) - .firstOrNull(), object1); - assertEquals(repository.find(where("id").eq(new Date(1482773720L))) - .firstOrNull(), object2); - } - - @Test - public void testWithIdInheritance() { - ObjectRepository repository = db.getRepository(ChildClass.class); - assertTrue(repository.hasIndex("id")); - assertTrue(repository.hasIndex("date")); - assertTrue(repository.hasIndex("text")); - - ChildClass childClass = new ChildClass(); - childClass.setName("first"); - childClass.setDate(new Date(100000L)); - childClass.setId(1L); - childClass.setText("I am first class"); - repository.insert(childClass); - - childClass = new ChildClass(); - childClass.setName("seconds"); - childClass.setDate(new Date(100001L)); - childClass.setId(2L); - childClass.setText("I am second class"); - repository.insert(childClass); - - childClass = new ChildClass(); - childClass.setName("third"); - childClass.setDate(new Date(100002L)); - childClass.setId(3L); - childClass.setText("I am third class"); - repository.insert(childClass); - - assertEquals(repository.find(where("text").text("class")).size(), 3); - assertEquals(repository.find(where("text").text("second")).size(), 0); // filtered in stop words - assertEquals(repository.find(where("date").eq(new Date(100000L))).size(), 1); - assertEquals(repository.find(where("id").eq(1L)).size(), 1); - } - - @Test - public void testAttributes() { - ObjectRepository repository = db.getRepository(WithDateId.class); - Attributes attributes = new Attributes(repository.getDocumentCollection().getName()); - repository.setAttributes(attributes); - assertEquals(repository.getAttributes(), attributes); - } - - @Test - public void testKeyedRepository() { - // an object repository of employees who are managers - ObjectRepository managerRepo = db.getRepository(Employee.class, "managers"); - - // an object repository of all employee - ObjectRepository employeeRepo = db.getRepository(Employee.class); - - // and object repository of employees who are developers - ObjectRepository developerRepo = db.getRepository(Employee.class, "developers"); - - Employee manager = new Employee(); - manager.setEmpId(1L); - manager.setAddress("abcd"); - manager.setJoinDate(new Date()); - - Employee developer = new Employee(); - developer.setEmpId(2L); - developer.setAddress("xyz"); - developer.setJoinDate(new Date()); - - managerRepo.insert(manager); - employeeRepo.insert(manager, developer); - developerRepo.insert(developer); - - assertTrue(db.hasRepository(Employee.class)); - assertTrue(db.hasRepository(Employee.class, "managers")); - assertTrue(db.hasRepository(Employee.class, "developers")); - - assertEquals(db.listRepositories().size(), 1); - assertEquals(db.listKeyedRepository().size(), 2); - - assertEquals(employeeRepo.find(where("address").eq("abcd")).size(), 1); - assertEquals(employeeRepo.find(where("address").eq("xyz")).size(), 1); - assertEquals(managerRepo.find(where("address").eq("xyz")).size(), 0); - assertEquals(managerRepo.find(where("address").eq("abcd")).size(), 1); - assertEquals(developerRepo.find(where("address").eq("xyz")).size(), 1); - assertEquals(developerRepo.find(where("address").eq("abcd")).size(), 0); - } - - @Test - public void testEntityRepository() { - ObjectRepository managerRepo = db.getRepository(EmployeeEntity.class, "managers"); - ObjectRepository employeeRepo = db.getRepository(EmployeeEntity.class); - ObjectRepository developerRepo = db.getRepository(EmployeeEntity.class, "developers"); - - managerRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); - employeeRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); - developerRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); - - boolean errored = false; - try { - NitriteCollection collection = db.getCollection("entity.employee"); - } catch (ValidationException e) { - errored = true; - } - assertTrue(errored); - - assertTrue(db.listRepositories().contains("entity.employee")); - assertEquals(db.listKeyedRepository().size(), 2); - assertEquals(db.listCollectionNames().size(), 0); - - assertTrue(managerRepo.hasIndex("firstName")); - assertTrue(managerRepo.hasIndex("lastName")); - assertTrue(employeeRepo.hasIndex("lastName")); - assertTrue(employeeRepo.hasIndex("lastName")); - - managerRepo.drop(); - assertEquals(db.listKeyedRepository().size(), 1); - } - - @Test - public void testIssue217() { - ObjectRepository employeeRepo = db.getRepository(EmployeeEntity.class); - AtomicInteger counter = new AtomicInteger(0); - employeeRepo.subscribe(eventInfo -> counter.incrementAndGet()); - - ObjectRepository employeeRepo2 = db.getRepository(EmployeeEntity.class); - employeeRepo2.insert(new EmployeeEntity()); - await().atMost(5, TimeUnit.SECONDS).until(() -> counter.get() == 1); - } - - @Data - @Entity(value = "entity.employee", indices = { - @Index(value = "firstName", type = IndexType.NonUnique), - @Index(value = "lastName", type = IndexType.NonUnique), - }) - private static class EmployeeEntity implements Mappable { - private static final Faker faker = new Faker(); - - @Id - private Long id; - private String firstName; - private String lastName; - - public EmployeeEntity() { - id = faker.number().randomNumber(); - firstName = faker.name().firstName(); - lastName = faker.name().lastName(); - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("id", id) - .put("firstName", firstName) - .put("lastName", lastName); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Long.class); - firstName = document.get("firstName", String.class); - lastName = document.get("lastName", String.class); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/ProjectionTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/ProjectionTest.java deleted file mode 100644 index b510b088e..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/ProjectionTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository; - -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.mapdb.repository.data.SubEmployee; -import org.junit.Test; - -import java.util.Iterator; - -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -public class ProjectionTest extends BaseObjectRepositoryTest { - - @Test - public void testHasMore() { - RecordStream iterable = employeeRepository.find().skipLimit(0, 5) - .project(SubEmployee.class); - assertFalse(iterable.isEmpty()); - } - - @Test - public void testSize() { - RecordStream iterable = employeeRepository.find().skipLimit(0, 5) - .project(SubEmployee.class); - assertEquals(iterable.size(), 5); - } - - @Test - public void testToString() { - RecordStream iterable = employeeRepository.find().skipLimit(0, 5) - .project(SubEmployee.class); - assertNotNull(iterable.toString()); - } - - @Test(expected = InvalidOperationException.class) - public void testRemove() { - RecordStream iterable = employeeRepository.find().skipLimit(0, 5) - .project(SubEmployee.class); - Iterator iterator = iterable.iterator(); - if (iterator.hasNext()) { - iterator.next(); - iterator.remove(); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/RepositoryFactoryTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/RepositoryFactoryTest.java deleted file mode 100644 index 859a822d6..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/RepositoryFactoryTest.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.*; -import org.dizitart.no2.collection.events.CollectionEventListener; -import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.common.concurrent.LockService; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexEntry; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.mapdb.Retry; -import org.dizitart.no2.mapdb.TestUtil; -import org.dizitart.no2.repository.RepositoryFactory; -import org.dizitart.no2.store.NitriteStore; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.util.Collection; - -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee - */ -public class RepositoryFactoryTest { - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testRepositoryFactory() { - RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); - assertNotNull(factory); - } - - @Test(expected = ValidationException.class) - public void testNullType() { - RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); - db = TestUtil.createDb(); - factory.getRepository(db.getConfig(), null, "dummy"); - } - - @Test - public void testNullCollection() { - RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); - db = TestUtil.createDb(); - factory.getRepository(db.getConfig(), DummyCollection.class, null); - } - - @Test(expected = ValidationException.class) - public void testNullContext() { - RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); - factory.getRepository(null, DummyCollection.class, "dummy"); - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - } - - private static class DummyCollection implements NitriteCollection { - - @Override - public WriteResult update(Filter filter, Document update, UpdateOptions updateOptions) { - return null; - } - - @Override - public WriteResult remove(Filter filter, boolean justOne) { - return null; - } - - @Override - public DocumentCursor find() { - return null; - } - - @Override - public DocumentCursor find(Filter filter) { - return null; - } - - @Override - public Document getById(NitriteId nitriteId) { - return null; - } - - @Override - public String getName() { - return null; - } - - @Override - public void createIndex(String field, IndexOptions indexOptions) { - - } - - @Override - public void rebuildIndex(String field, boolean isAsync) { - - } - - @Override - public Collection listIndices() { - return null; - } - - @Override - public boolean hasIndex(String field) { - return false; - } - - @Override - public boolean isIndexing(String field) { - return false; - } - - @Override - public void dropIndex(String field) { - - } - - @Override - public void dropAllIndices() { - - } - - @Override - public WriteResult insert(Document[] elements) { - return null; - } - - @Override - public WriteResult update(Document element, boolean insertIfAbsent) { - return null; - } - - @Override - public WriteResult remove(Document element) { - return null; - } - - @Override - public void clear() { - - } - - @Override - public void drop() { - - } - - @Override - public boolean isDropped() { - return false; - } - - @Override - public boolean isOpen() { - return false; - } - - @Override - public void close() { - - } - - @Override - public long size() { - return 0; - } - - @Override - public NitriteStore getStore() { - return null; - } - - @Override - public void subscribe(CollectionEventListener listener) { - - } - - @Override - public void unsubscribe(CollectionEventListener listener) { - - } - - @Override - public Attributes getAttributes() { - return null; - } - - @Override - public void setAttributes(Attributes attributes) { - - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/RepositoryJoinTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/RepositoryJoinTest.java deleted file mode 100644 index 400de9ac3..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/RepositoryJoinTest.java +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository; - -import lombok.Data; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.Lookup; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.mapdb.MapDBModule; -import org.dizitart.no2.mapdb.MapDBModuleBuilder; -import org.dizitart.no2.mapdb.Retry; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Id; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.*; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.mapdb.DbTestOperations.getRandomTempDbFile; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -@RunWith(value = Parameterized.class) -public class RepositoryJoinTest { - @Parameterized.Parameter - public boolean inMemory = false; - @Parameterized.Parameter(value = 1) - public boolean isProtected = false; - - protected Nitrite db; - private final String fileName = getRandomTempDbFile(); - private ObjectRepository personRepository; - private ObjectRepository
addressRepository; - - @Rule - public Retry retry = new Retry(3); - - @Parameterized.Parameters(name = "InMemory = {0}, Protected = {1}") - public static Collection data() { - return Arrays.asList(new Object[][]{ - {false, false}, - {false, true}, - {true, false}, - {true, true}, - }); - } - - @Before - public void setUp() { - openDb(); - - personRepository = db.getRepository(Person.class); - addressRepository = db.getRepository(Address.class); - - for (int i = 0; i < 10; i++) { - Person person = new Person(); - person.setId(Integer.toString(i)); - person.setName("Person " + i); - personRepository.insert(person); - - Address address = new Address(); - address.setPersonId(Integer.toString(i)); - address.setStreet("Street address " + i); - addressRepository.insert(address); - - if (i == 5) { - Address address2 = new Address(); - address2.setPersonId(Integer.toString(i)); - address2.setStreet("Street address 2nd " + i); - addressRepository.insert(address2); - } - } - } - - private void openDb() { - MapDBModuleBuilder builder = MapDBModule.withConfig(); - - if (!inMemory) { - builder.filePath(fileName); - } - - MapDBModule storeModule = builder.build(); - NitriteBuilder nitriteBuilder = Nitrite.builder() - .fieldSeparator(".") - .loadModule(storeModule); - - if (isProtected) { - db = nitriteBuilder.openOrCreate("test-user1", "test-password1"); - } else { - db = nitriteBuilder.openOrCreate(); - } - } - - @After - public void clear() throws IOException { - if (personRepository != null && !personRepository.isDropped()) { - personRepository.remove(ALL); - } - - if (addressRepository != null && !addressRepository.isDropped()) { - addressRepository.remove(ALL); - } - - if (db != null) { - db.commit(); - db.close(); - } - - if (!inMemory) { - Files.delete(Paths.get(fileName)); - } - } - - @Test - public void testJoin() { - Lookup lookup = new Lookup(); - lookup.setLocalField("id"); - lookup.setForeignField("personId"); - lookup.setTargetField("addresses"); - - RecordStream result - = personRepository.find().join(addressRepository.find(), lookup, - PersonDetails.class); - assertEquals(result.size(), 10); - - for (PersonDetails personDetails : result) { - Address[] addresses = personDetails.addresses.toArray(new Address[0]); - if (personDetails.id.equals("5")) { - assertEquals(addresses.length, 2); - } else { - assertEquals(addresses.length, 1); - assertEquals(addresses[0].personId, personDetails.getId()); - } - } - - result = personRepository.find().skipLimit(0, 5).join(addressRepository.find(), lookup, - PersonDetails.class); - - assertEquals(result.size(), 5); - assertFalse(result.isEmpty()); - assertNotNull(result.toString()); - } - - @Test(expected = InvalidOperationException.class) - public void testRemove() { - Lookup lookup = new Lookup(); - lookup.setLocalField("id"); - lookup.setForeignField("personId"); - lookup.setTargetField("addresses"); - - RecordStream result - = personRepository.find().join(addressRepository.find(), lookup, - PersonDetails.class); - assertEquals(result.size(), 10); - - Iterator iterator = result.iterator(); - if (iterator.hasNext()) { - iterator.next(); - iterator.remove(); - } - } - - @Data - public static class Person implements Mappable { - @Id - private NitriteId nitriteId; - private String id; - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("nitriteId", nitriteId) - .put("id", id) - .put("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - nitriteId = document.get("nitriteId", NitriteId.class); - id = document.get("id", String.class); - name = document.get("name", String.class); - } - } - - @Data - public static class Address implements Mappable { - @Id - private NitriteId nitriteId; - private String personId; - private String street; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("nitriteId", nitriteId) - .put("personId", personId) - .put("street", street); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - nitriteId = document.get("nitriteId", NitriteId.class); - personId = document.get("personId", String.class); - street = document.get("street", String.class); - } - } - - @Data - public static class PersonDetails implements Mappable { - @Id - private NitriteId nitriteId; - private String id; - private String name; - private List
addresses; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("nitriteId", nitriteId) - .put("personId", id) - .put("street", name) - .put("addresses", addresses); - } - - @Override - @SuppressWarnings("unchecked") - public void read(NitriteMapper mapper, Document document) { - nitriteId = document.get("nitriteId", NitriteId.class); - id = document.get("id", String.class); - name = document.get("name", String.class); - Set documents = document.get("addresses", Set.class); - this.addresses = new ArrayList<>(); - for (Document doc : documents) { - Address address = new Address(); - address.read(mapper, doc); - addresses.add(address); - } - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/RepositoryModificationTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/RepositoryModificationTest.java deleted file mode 100644 index 0cd95fba9..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/RepositoryModificationTest.java +++ /dev/null @@ -1,633 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.InvalidIdException; -import org.dizitart.no2.exceptions.UniqueConstraintException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexEntry; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapdb.repository.data.*; -import org.dizitart.no2.repository.Cursor; -import org.dizitart.no2.repository.ObjectRepository; -import org.junit.Test; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Collection; -import java.util.Date; -import java.util.Locale; - -import static org.awaitility.Awaitility.await; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.*; - - -/** - * @author Anindya Chatterjee. - */ -public class RepositoryModificationTest extends BaseObjectRepositoryTest { - - @Test - public void testCreateIndex() { - assertTrue(companyRepository.hasIndex("companyName")); - assertFalse(companyRepository.hasIndex("dateCreated")); - - companyRepository.createIndex("dateCreated", IndexOptions.indexOptions(IndexType.NonUnique)); - assertTrue(companyRepository.hasIndex("dateCreated")); - assertFalse(companyRepository.isIndexing("dateCreated")); - } - - @Test - public void testRebuildIndex() { - companyRepository.createIndex("dateCreated", IndexOptions.indexOptions(IndexType.NonUnique)); - assertFalse(companyRepository.isIndexing("dateCreated")); - - companyRepository.rebuildIndex("dateCreated", true); - assertTrue(companyRepository.isIndexing("dateCreated")); - - await().until(() -> !companyRepository.isIndexing("dateCreated")); - } - - @Test - public void testListIndexes() { - Collection indices = companyRepository.listIndices(); - assertEquals(indices.size(), 2); - - companyRepository.createIndex("dateCreated", IndexOptions.indexOptions(IndexType.NonUnique)); - indices = companyRepository.listIndices(); - assertEquals(indices.size(), 3); - } - - @Test - public void testDropIndex() { - testListIndexes(); - companyRepository.dropIndex("dateCreated"); - Collection indices = companyRepository.listIndices(); - assertEquals(indices.size(), 2); - } - - @Test - public void testDropAllIndex() { - testListIndexes(); - companyRepository.dropAllIndices(); - Collection indices = companyRepository.listIndices(); - assertEquals(indices.size(), 0); - } - - @Test - public void testCompanyRecord() { - Cursor cursor = companyRepository.find(); - assertEquals(cursor.size(), 10); - assertFalse(cursor.isEmpty()); - } - - @Test - public void testInsert() { - Company company = DataGenerator.generateCompanyRecord(); - Cursor cursor = companyRepository.find(); - assertEquals(cursor.size(), 10); - - companyRepository.insert(company); - cursor = companyRepository.find(); - assertEquals(cursor.size(), 11); - - Company company1 = DataGenerator.generateCompanyRecord(); - Company company2 = DataGenerator.generateCompanyRecord(); - companyRepository.insert(new Company[]{company1, company2}); - cursor = companyRepository.find(); - assertEquals(cursor.size(), 13); - } - - @Test - public void testUpdateWithFilter() { - employeeRepository.remove(Filter.ALL); - - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("abcd road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(new Date()); - Note empNote = new Note(); - empNote.setNoteId(23L); - empNote.setText("sample text note"); - employee.setEmployeeNote(empNote); - - employeeRepository.insert(employee); - Cursor result = employeeRepository.find(); - assertEquals(result.size(), 1); - for (Employee e : result) { - assertEquals(e.getAddress(), "abcd road"); - } - - Employee updated = new Employee(employee); - updated.setAddress("xyz road"); - WriteResult writeResult = employeeRepository.update(where("empId").eq(12L), updated); - assertEquals(writeResult.getAffectedCount(), 1); - result = employeeRepository.find(); - assertEquals(result.size(), 1); - for (Employee e : result) { - assertEquals(e.getAddress(), "xyz road"); - } - } - - @Test - public void testUpdateWithJustOnceFalse() throws ParseException { - Date joiningDate = new Date(); - prepareUpdateWithOptions(joiningDate); - - SimpleDateFormat simpleDateFormat - = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); - Date newJoiningDate = simpleDateFormat.parse("2012-07-01T16:02:48.440Z"); - - Document updated1 = createDocument(); - updated1.put("joinDate", newJoiningDate); - - WriteResult writeResult - = employeeRepository.update(where("empId").eq(12L), updated1, false); - assertEquals(writeResult.getAffectedCount(), 1); - - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 1); - result = employeeRepository.find(where("joinDate").eq(newJoiningDate)); - assertEquals(result.size(), 1); - - employeeRepository.remove(Filter.ALL); - prepareUpdateWithOptions(joiningDate); - result = employeeRepository.find(); - assertEquals(result.size(), 2); - - Document update = createDocument(); - update.put("joinDate", newJoiningDate); - - writeResult = employeeRepository.update(where("joinDate").eq(joiningDate), update, false); - assertEquals(writeResult.getAffectedCount(), 2); - - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - - result = employeeRepository.find(where("joinDate").eq(newJoiningDate)); - assertEquals(result.size(), 2); - } - - @Test - public void testUpsertTrue() { - Date joiningDate = new Date(); - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("some road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(joiningDate); - Note empNote1 = new Note(); - empNote1.setNoteId(23L); - empNote1.setText("sample text note"); - employee.setEmployeeNote(empNote1); - - WriteResult writeResult - = employeeRepository.update(where("empId").eq(12), employee, true); - assertEquals(writeResult.getAffectedCount(), 1); - - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 1); - } - - @Test - public void testUpsertFalse() { - Date joiningDate = new Date(); - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("some road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(joiningDate); - Note empNote1 = new Note(); - empNote1.setNoteId(23L); - empNote1.setText("sample text note"); - employee.setEmployeeNote(empNote1); - - WriteResult writeResult - = employeeRepository.update(where("empId").eq(12), employee, false); - assertEquals(writeResult.getAffectedCount(), 0); - - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - } - - @Test - public void testDeleteFilterAndWithOutOption() { - Date joiningDate = new Date(); - prepareUpdateWithOptions(joiningDate); - - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 2); - - WriteResult writeResult = employeeRepository.remove(where("joinDate").eq(joiningDate)); - assertEquals(writeResult.getAffectedCount(), 2); - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - } - - @Test - public void testDeleteFilterAndWithOption() { - Date joiningDate = new Date(); - prepareUpdateWithOptions(joiningDate); - - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 2); - - WriteResult writeResult = employeeRepository.remove(where("joinDate").eq(joiningDate), true); - assertEquals(writeResult.getAffectedCount(), 1); - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 1); - } - - @Test - public void testEmployeeRecord() { - Iterable totalResult = employeeRepository.find(); - int occurrence = 0; - for (Employee employee : totalResult) { - if (employee.getEmployeeNote().getText().toLowerCase().contains("class aptent")) { - occurrence++; - } - } - - Cursor cursor = employeeRepository.find(where("employeeNote.text").text("Class aptent")); - assertEquals(cursor.size(), occurrence); - } - - @Test - public void testUpdateWithOptions() { - Employee employee = employeeRepository.find().firstOrNull(); - - Document update = createDocument(); - update.put("address", "new address"); - - WriteResult writeResult - = employeeRepository.update(where("empId").eq(employee.getEmpId()), update, false); - assertEquals(writeResult.getAffectedCount(), 1); - - Employee byId = employeeRepository.getById(employee.getEmpId()); - assertEquals(byId.getAddress(), "new address"); - assertEquals(byId.getEmpId(), employee.getEmpId()); - - update.put("address", "another address"); - employeeRepository.update(where("empId").eq(employee.getEmpId()), update); - - byId = employeeRepository.getById(employee.getEmpId()); - assertEquals(byId.getAddress(), "another address"); - assertEquals(byId.getEmpId(), employee.getEmpId()); - } - - @Test(expected = InvalidIdException.class) - public void testMultiUpdateWithObject() { - employeeRepository.remove(Filter.ALL); - - Date now = new Date(); - Employee employee1 = new Employee(); - employee1.setEmpId(1L); - employee1.setAddress("abcd"); - employee1.setJoinDate(now); - - Employee employee2 = new Employee(); - employee2.setEmpId(2L); - employee2.setAddress("xyz"); - employee2.setJoinDate(now); - employeeRepository.insert(employee1, employee2); - - Employee update = new Employee(); - update.setAddress("new address"); - - WriteResult writeResult - = employeeRepository.update(where("joinDate").eq(now), update, false); - assertEquals(writeResult.getAffectedCount(), 0); - } - - @Test - public void testUpdateNull() { - Employee employee = employeeRepository.find().firstOrNull(); - Employee newEmployee = new Employee(employee); - newEmployee.setJoinDate(null); - - Employee result = employeeRepository.find(where("empId").eq(employee.getEmpId())).firstOrNull(); - assertNotNull(result.getJoinDate()); - - WriteResult writeResult = employeeRepository.update(newEmployee, false); - assertEquals(writeResult.getAffectedCount(), 1); - - result = employeeRepository.find(where("empId").eq(employee.getEmpId())).firstOrNull(); - assertNull(result.getJoinDate()); - - // update with object filter and item and set id different - } - - @Test - public void testUpdateWithChangedId() { - Employee employee = employeeRepository.find().firstOrNull(); - Long oldId = employee.getEmpId(); - long count = employeeRepository.size(); - - Employee newEmployee = new Employee(employee); - newEmployee.setEmpId(50L); - - Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); - assertNotNull(result.getJoinDate()); - - WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); - assertEquals(writeResult.getAffectedCount(), 1); - - assertEquals(count, employeeRepository.size()); - Cursor cursor = employeeRepository.find(where("empId").eq(oldId)); - assertEquals(cursor.size(), 0); - } - - @Test(expected = InvalidIdException.class) - public void testUpdateWithNullId() { - Employee employee = employeeRepository.find().firstOrNull(); - Long oldId = employee.getEmpId(); - - Employee newEmployee = new Employee(employee); - newEmployee.setEmpId(null); - - Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); - assertNotNull(result.getJoinDate()); - - WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); - assertEquals(writeResult.getAffectedCount(), 1); - } - - @Test(expected = UniqueConstraintException.class) - public void testUpdateWithDuplicateId() { - Employee employee = employeeRepository.find().firstOrNull(); - Long oldId = employee.getEmpId(); - long count = employeeRepository.size(); - - Employee newEmployee = new Employee(employee); - newEmployee.setEmpId(5L); - - Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); - assertNotNull(result.getJoinDate()); - - WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); - assertEquals(writeResult.getAffectedCount(), 1); - - assertEquals(count, employeeRepository.size()); - Cursor cursor = employeeRepository.find(where("empId").eq(oldId)); - assertEquals(cursor.size(), 0); - } - - @Test - public void testUpdateWithObject() { - Employee employee = employeeRepository.find().firstOrNull(); - Employee newEmployee = new Employee(employee); - - Long id = employee.getEmpId(); - String address = employee.getAddress(); - newEmployee.setAddress("new address"); - - WriteResult writeResult = employeeRepository.update(newEmployee); - assertEquals(writeResult.getAffectedCount(), 1); - - Employee emp = employeeRepository.find(where("empId").eq(id)).firstOrNull(); - assertNotEquals(address, emp.getAddress()); - assertEquals(employee.getEmpId(), emp.getEmpId()); - assertEquals(employee.getJoinDate(), emp.getJoinDate()); - assertArrayEquals(employee.getBlob(), emp.getBlob()); - } - - @Test - public void testUpsertWithObject() { - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("some road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(new Date()); - Note empNote = new Note(); - empNote.setNoteId(23L); - empNote.setText("sample text note"); - employee.setEmployeeNote(empNote); - - WriteResult writeResult = employeeRepository.update(employee, false); - assertEquals(writeResult.getAffectedCount(), 0); - writeResult = employeeRepository.update(employee, true); - assertEquals(writeResult.getAffectedCount(), 1); - - Employee emp = employeeRepository.find(where("empId").eq(12L)).firstOrNull(); - assertEquals(emp, employee); - } - - @Test - public void testRemoveObject() { - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("some road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(new Date()); - Note empNote = new Note(); - empNote.setNoteId(23L); - empNote.setText("sample text note"); - employee.setEmployeeNote(empNote); - - long size = employeeRepository.size(); - - employeeRepository.insert(employee); - assertEquals(employeeRepository.size(), size + 1); - - employeeRepository.remove(employee); - assertEquals(employeeRepository.size(), size); - - Employee emp = employeeRepository.find(where("empId").eq(12L)).firstOrNull(); - assertNull(emp); - } - - private void prepareUpdateWithOptions(Date joiningDate) { - employeeRepository.remove(Filter.ALL); - - Employee employee1 = new Employee(); - employee1.setCompany(null); - employee1.setAddress("some road"); - employee1.setBlob(new byte[]{1, 2, 125}); - employee1.setEmpId(12L); - employee1.setJoinDate(joiningDate); - Note empNote1 = new Note(); - empNote1.setNoteId(23L); - empNote1.setText("sample text note"); - employee1.setEmployeeNote(empNote1); - - Employee employee2 = new Employee(); - employee2.setCompany(null); - employee2.setAddress("other road"); - employee2.setBlob(new byte[]{10, 12, 25}); - employee2.setEmpId(2L); - employee2.setJoinDate(joiningDate); - Note empNote2 = new Note(); - empNote2.setNoteId(2L); - empNote2.setText("some random note"); - employee2.setEmployeeNote(empNote2); - - employeeRepository.insert(employee1, employee2); - Cursor result = employeeRepository.find(); - assertEquals(result.size(), 2); - for (Employee e : result.project(Employee.class)) { - assertEquals(e.getJoinDate(), joiningDate); - } - } - - @Test - public void testUpdateWithDoc() { - Note note = new Note(); - note.setNoteId(10L); - note.setText("some note text"); - - Document document = createDocument("address", "some address") - .put("employeeNote", note); - - WriteResult result = employeeRepository.update(Filter.ALL, document); - assertEquals(result.getAffectedCount(), 10); - } - - @Test - public void testDeleteIteratorNPE() { - ObjectRepository notes = db.getRepository(Note.class); - Note one = new Note(); - one.setText("Jane"); - one.setNoteId(1L); - Note two = new Note(); - two.setText("Jill"); - two.setNoteId(2L); - - notes.insert(one, two); - - WriteResult writeResult = notes.remove(where("text").eq("Pete")); - for (NitriteId id : writeResult) { - assertNotNull(id); - } - } - - @Test - public void testDelete() { - ObjectRepository repo = db.getRepository(WithNitriteId.class); - WithNitriteId one = new WithNitriteId(); - one.setName("Jane"); - repo.insert(one); - - WithNitriteId note = repo.find().firstOrNull(); - repo.remove(note); - - assertNull(repo.getById(one.idField)); - } - - /* - * Upsert Use Cases - * - * 1. Object does not exists - * a. if upsert true, it will insert - * b. if upsert false, nothing happens - * 2. Object exists - * a. if upsert true, it will update, old id remains same - * b. if upsert false, it will update, old id remains same - * - * */ - - @Test - public void testUpdateObjectNotExistsUpsertTrue() { - ObjectRepository repo = db.getRepository(InternalClass.class); - InternalClass a = new InternalClass(); - a.setId(1); - a.setName("first"); - repo.insert(a); - - a = new InternalClass(); - a.setId(2); - a.setName("second"); - - // it will insert as new object - repo.update(a, true); - assertEquals(repo.size(), 2); - } - - @Test - public void testUpdateObjectNotExistsUpsertFalse() { - ObjectRepository repo = db.getRepository(InternalClass.class); - InternalClass a = new InternalClass(); - a.setId(1); - a.setName("first"); - repo.insert(a); - - a = new InternalClass(); - a.setId(2); - a.setName("second"); - - // no changes will happen to repository - repo.update(a, false); - assertEquals(repo.size(), 1); - assertEquals(repo.find().firstOrNull().getId(), 1); - assertEquals(repo.find().firstOrNull().getName(), "first"); - } - - @Test - public void testUpdateObjectExistsUpsertTrue() { - ObjectRepository repo = db.getRepository(InternalClass.class); - InternalClass a = new InternalClass(); - a.setId(1); - a.setName("first"); - repo.insert(a); - - a = new InternalClass(); - a.setId(1); - a.setName("second"); - - // update existing object, keep id same - repo.update(a, true); - assertEquals(repo.size(), 1); - assertEquals(repo.find().firstOrNull().getId(), 1); - assertEquals(repo.find().firstOrNull().getName(), "second"); - } - - @Test - public void testUpdateObjectExistsUpsertFalse() { - ObjectRepository repo = db.getRepository(InternalClass.class); - InternalClass a = new InternalClass(); - a.setId(1); - a.setName("first"); - repo.insert(a); - - a = new InternalClass(); - a.setId(1); - a.setName("second"); - - // update existing object, keep id same - repo.update(a, false); - assertEquals(repo.size(), 1); - assertEquals(repo.find().firstOrNull().getId(), 1); - assertEquals(repo.find().firstOrNull().getName(), "second"); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/RepositorySearchTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/RepositorySearchTest.java deleted file mode 100644 index 3bb0cf79d..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/RepositorySearchTest.java +++ /dev/null @@ -1,603 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository; - -import lombok.Getter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.exceptions.InvalidIdException; -import org.dizitart.no2.exceptions.NotIdentifiableException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.mapdb.repository.data.*; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.Cursor; -import org.dizitart.no2.repository.ObjectRepository; -import org.junit.Test; - -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.List; - -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.$; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class RepositorySearchTest extends BaseObjectRepositoryTest { - @Test - public void testFindWithOptions() { - Cursor cursor = employeeRepository.find().skipLimit(0, 1); - assertEquals(cursor.size(), 1); - assertNotNull(cursor.firstOrNull()); - } - - @Test - public void testEmployeeProjection() { - List employeeList = employeeRepository.find().toList(); - List subEmployeeList - = employeeRepository.find().project(SubEmployee.class).toList(); - - assertNotNull(employeeList); - assertNotNull(subEmployeeList); - - assertTrue(employeeList.size() > 0); - assertTrue(subEmployeeList.size() > 0); - - assertEquals(employeeList.size(), subEmployeeList.size()); - - for (int i = 0; i < subEmployeeList.size(); i++) { - Employee employee = employeeList.get(i); - SubEmployee subEmployee = subEmployeeList.get(i); - - assertEquals(employee.getEmpId(), subEmployee.getEmpId()); - assertEquals(employee.getJoinDate(), subEmployee.getJoinDate()); - assertEquals(employee.getAddress(), subEmployee.getAddress()); - } - - Cursor cursor = employeeRepository.find(); - assertNotNull(cursor.firstOrNull()); - assertNotNull(cursor.toString()); - assertEquals(cursor.toList().size(), employeeList.size()); - assertNotNull(cursor.firstOrNull()); - assertEquals(cursor.toList().size(), employeeList.size()); - } - - @Test - public void testEmptyResultProjection() { - employeeRepository.remove(ALL); - assertNull(employeeRepository.find().firstOrNull()); - - assertNull(employeeRepository.find(where("empId").eq(-1)) - .firstOrNull()); - } - - @Test - public void testGetById() { - ObjectRepository empRepo = db.getRepository(Employee.class); - Employee e1 = DataGenerator.generateEmployee(); - Employee e2 = DataGenerator.generateEmployee(); - Employee e3 = DataGenerator.generateEmployee(); - Employee e4 = DataGenerator.generateEmployee(); - - e1.setEmpId(1000000L); - e2.setEmpId(2000000L); - e3.setEmpId(3000000L); - e4.setEmpId(4000000L); - - empRepo.insert(e1, e2, e3, e4); - - Employee byId = empRepo.getById(2000000L); - assertEquals(byId, e2); - } - - @Test(expected = NotIdentifiableException.class) - public void testGetByIdNoId() { - ObjectRepository repository = db.getRepository(Note.class); - Note n1 = DataGenerator.randomNote(); - Note n2 = DataGenerator.randomNote(); - Note n3 = DataGenerator.randomNote(); - - assert n1 != null; - n1.setNoteId(1000000L); - assert n2 != null; - n2.setNoteId(2000000L); - assert n3 != null; - n3.setNoteId(3000000L); - - repository.insert(n1, n2, n3); - - repository.getById(2000000L); - } - - @Test(expected = InvalidIdException.class) - public void testGetByIdNullId() { - ObjectRepository empRepo = db.getRepository(Employee.class); - Employee e1 = DataGenerator.generateEmployee(); - Employee e2 = DataGenerator.generateEmployee(); - Employee e3 = DataGenerator.generateEmployee(); - Employee e4 = DataGenerator.generateEmployee(); - - e1.setEmpId(1000000L); - e2.setEmpId(2000000L); - e3.setEmpId(3000000L); - e4.setEmpId(4000000L); - - empRepo.insert(e1, e2, e3, e4); - - empRepo.getById(null); - } - - @Test(expected = InvalidIdException.class) - public void testGetByIdWrongType() { - ObjectRepository empRepo = db.getRepository(Employee.class); - Employee e1 = DataGenerator.generateEmployee(); - Employee e2 = DataGenerator.generateEmployee(); - Employee e3 = DataGenerator.generateEmployee(); - Employee e4 = DataGenerator.generateEmployee(); - - e1.setEmpId(1000000L); - e2.setEmpId(2000000L); - e3.setEmpId(3000000L); - e4.setEmpId(4000000L); - - empRepo.insert(e1, e2, e3, e4); - - Employee byId = empRepo.getById("employee"); - assertNull(byId); - } - - @Test - public void testEqualFilterById() { - Employee employee = employeeRepository.find().firstOrNull(); - long empId = employee.getEmpId(); - Employee emp = employeeRepository.find(where("empId").eq(empId)) - .project(Employee.class).firstOrNull(); - assertEquals(employee, emp); - } - - @Test - public void testEqualFilter() { - Employee employee = employeeRepository.find() - .firstOrNull(); - - Employee emp = employeeRepository.find(where("joinDate").eq(employee.getJoinDate())) - .project(Employee.class) - .firstOrNull(); - assertEquals(employee, emp); - } - - @Test - public void testStringEqualFilter() { - ObjectRepository repository = db.getRepository(ProductScore.class); - - ProductScore object = new ProductScore(); - object.setProduct("test"); - object.setScore(1); - repository.insert(object); - - object = new ProductScore(); - object.setProduct("test"); - object.setScore(2); - repository.insert(object); - - object = new ProductScore(); - object.setProduct("another-test"); - object.setScore(3); - repository.insert(object); - - assertEquals(repository.find(where("product").eq("test")).size(), 2); - } - - @Test - public void testAndFilter() { - Employee emp = employeeRepository.find().firstOrNull(); - - long id = emp.getEmpId(); - String address = emp.getAddress(); - Date joinDate = emp.getJoinDate(); - - Employee employee = employeeRepository.find( - where("empId").eq(id) - .and( - where("address").regex(address) - .and( - where("joinDate").eq(joinDate)))).firstOrNull(); - - assertEquals(emp, employee); - } - - @Test - public void testOrFilter() { - Employee emp = employeeRepository.find().firstOrNull(); - long id = emp.getEmpId(); - - Employee employee = employeeRepository.find( - where("empId").eq(id) - .or( - where("address").regex("n/a") - .or( - where("joinDate").eq(null)))).firstOrNull(); - - assertEquals(emp, employee); - } - - @Test - public void testNotFilter() { - Employee emp = employeeRepository.find().firstOrNull(); - long id = emp.getEmpId(); - - Employee employee = employeeRepository.find( - where("empId").eq(id).not()).firstOrNull(); - assertNotEquals(emp, employee); - } - - @Test - public void testGreaterFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Ascending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").gt(id)) - .toList(); - - assertFalse(employeeList.contains(emp)); - assertEquals(employeeList.size(), 9); - } - - @Test - public void testGreaterEqualFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Ascending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").gte(id)) - .toList(); - - assertTrue(employeeList.contains(emp)); - assertEquals(employeeList.size(), 10); - } - - @Test - public void testLesserThanFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Descending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").lt(id)) - .toList(); - - assertFalse(employeeList.contains(emp)); - assertEquals(employeeList.size(), 9); - } - - @Test - public void testLesserEqualFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Descending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").lte(id)) - .toList(); - - assertTrue(employeeList.contains(emp)); - assertEquals(employeeList.size(), 10); - } - - @Test - public void testTextFilter() { - Employee emp = employeeRepository.find().firstOrNull(); - String text = emp.getEmployeeNote().getText(); - - List employeeList = employeeRepository.find(where("employeeNote.text").text(text)) - .toList(); - - assertTrue(employeeList.contains(emp)); - } - - @Test - public void testRegexFilter() { - RecordStream employees = employeeRepository.find(); - int count = employees.toList().size(); - - List employeeList = employeeRepository.find(where("employeeNote.text").regex(".*")) - .toList(); - - assertEquals(employeeList.size(), count); - } - - @Test - public void testInFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Descending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").in(id, id - 1, id - 2)) - .toList(); - - assertTrue(employeeList.contains(emp)); - assertEquals(employeeList.size(), 3); - - employeeList = employeeRepository.find(where("empId").in(id - 1, id - 2)).toList(); - assertEquals(employeeList.size(), 2); - } - - @Test - public void testNotInFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Descending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").notIn(id, id - 1, id - 2)) - .toList(); - - assertFalse(employeeList.contains(emp)); - assertEquals(employeeList.size(), 7); - - employeeList = employeeRepository.find(where("empId").notIn(id - 1, id - 2)).toList(); - assertEquals(employeeList.size(), 8); - } - - @Test - public void testElemMatchFilter() { - final ProductScore score1 = new ProductScore("abc", 10); - final ProductScore score2 = new ProductScore("abc", 8); - final ProductScore score3 = new ProductScore("abc", 7); - final ProductScore score4 = new ProductScore("xyz", 5); - final ProductScore score5 = new ProductScore("xyz", 7); - final ProductScore score6 = new ProductScore("xyz", 8); - - ObjectRepository repository = db.getRepository(ElemMatch.class); - ElemMatch e1 = new ElemMatch(); - e1.setId(1); - e1.setStrArray(new String[]{"a", "b"}); - e1.setProductScores(new ProductScore[]{score1, score4}); - ElemMatch e2 = new ElemMatch(); - e2.setId(2); - e2.setStrArray(new String[]{"d", "e"}); - e2.setProductScores(new ProductScore[]{score2, score5}); - ElemMatch e3 = new ElemMatch(); - e3.setId(3); - e3.setStrArray(new String[]{"a", "f"}); - e3.setProductScores(new ProductScore[]{score3, score6}); - - repository.insert(e1, e2, e3); - - List elements = repository.find( - where("productScores").elemMatch( - where("product").eq("xyz") - .and(where("score").gte(8)))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("score").lte(8).not())).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("product").eq("xyz") - .or(where("score").gte(8)))).toList(); - assertEquals(elements.size(), 3); - - elements = repository.find( - where("productScores").elemMatch( - where("product").eq("xyz"))).toList(); - assertEquals(elements.size(), 3); - - elements = repository.find( - where("productScores").elemMatch( - where("score").gte(10))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("score").gt(8))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("score").lt(7))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("score").lte(7))).toList(); - assertEquals(elements.size(), 3); - - elements = repository.find( - where("productScores").elemMatch( - where("score").in(7, 8))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find( - where("productScores").elemMatch( - where("score").notIn(7, 8))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("product").regex("xyz"))).toList(); - assertEquals(elements.size(), 3); - - elements = repository.find(where("strArray").elemMatch($.eq("a"))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find( - where("strArray").elemMatch( - $.eq("a") - .or($.eq("f") - .or($.eq("b"))).not())).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find(where("strArray").elemMatch($.gt("e"))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find(where("strArray").elemMatch($.gte("e"))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find(where("strArray").elemMatch($.lte("b"))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find(where("strArray").elemMatch($.lt("a"))).toList(); - assertEquals(elements.size(), 0); - - elements = repository.find(where("strArray").elemMatch($.in("a", "f"))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find(where("strArray").elemMatch($.regex("a"))).toList(); - assertEquals(elements.size(), 2); - } - - @Test - public void testFilterAll() { - ObjectRepository repository = db.getRepository(ElemMatch.class); - Cursor cursor = repository.find(ALL); - assertNotNull(cursor); - assertEquals(cursor.size(), 0); - - repository.insert(new ElemMatch()); - cursor = repository.find(ALL); - assertNotNull(cursor); - assertEquals(cursor.size(), 1); - } - - @Test - public void testEqualsOnTextIndex() { - PersonEntity p1 = new PersonEntity("jhonny"); - PersonEntity p2 = new PersonEntity("jhonny"); - PersonEntity p3 = new PersonEntity("jhonny"); - - ObjectRepository repository = db.getRepository(PersonEntity.class); - repository.insert(p1); - repository.insert(p2); - repository.insert(p3); - - List sameNamePeople = repository.find(where("name").eq("jhonny")).toList(); - assertEquals(sameNamePeople.size(), 3); - - sameNamePeople = repository.find(where("name").eq("JHONNY")).toList(); - assertEquals(sameNamePeople.size(), 0); - - sameNamePeople = repository.find(where("name").text("jhonny")).toList(); - assertEquals(sameNamePeople.size(), 3); - - sameNamePeople = repository.find(where("name").text("JHONNY")).toList(); - assertEquals(sameNamePeople.size(), 3); - - sameNamePeople = repository.find(where("name").eq("jhon*")).toList(); - assertEquals(sameNamePeople.size(), 0); - - sameNamePeople = repository.find(where("name").text("jhon*")).toList(); - assertEquals(sameNamePeople.size(), 3); - } - - @Test - public void testIssue62() { - PersonEntity p1 = new PersonEntity("abcd"); - p1.setStatus("Married"); - - PersonEntity p2 = new PersonEntity("efgh"); - p2.setStatus("Married"); - - PersonEntity p3 = new PersonEntity("ijkl"); - p3.setStatus("Un-Married"); - - ObjectRepository repository = db.getRepository(PersonEntity.class); - repository.insert(p1); - repository.insert(p2); - repository.insert(p3); - - Filter married = where("status").eq("Married"); - - assertEquals(repository.find(married).size(), 2); - assertEquals(repository.find(married).sort("status", SortOrder.Descending).size(), 2); - - assertEquals(repository.find().sort("status", SortOrder.Descending).firstOrNull().getStatus(), "Un-Married"); - - assertEquals(repository.find().sort("status", SortOrder.Ascending).size(), 3); - assertEquals(repository.find().sort("status", SortOrder.Ascending).firstOrNull().getStatus(), "Married"); - } - - @Test - public void testRepeatableIndexAnnotation() { - ObjectRepository repo = db.getRepository(RepeatableIndexTest.class); - RepeatableIndexTest first = new RepeatableIndexTest(); - first.setAge(12); - first.setFirstName("fName"); - first.setLastName("lName"); - repo.insert(first); - - assertTrue(repo.hasIndex("firstName")); - assertTrue(repo.hasIndex("age")); - assertTrue(repo.hasIndex("lastName")); - - assertEquals(repo.find(where("age").eq(12)).firstOrNull(), first); - } - - @Test - public void testIdSet() { - Cursor employees = employeeRepository.find().sort("empId", SortOrder.Ascending); - assertEquals(employees.size(), 10); - } - - @Test - public void testBetweenFilter() { - @Getter - class TestData implements Mappable { - private Date age; - - public TestData(Date age) { - this.age = age; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("age", age); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - age = document.get("age", Date.class); - } - } - - TestData data1 = new TestData(new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime()); - TestData data2 = new TestData(new GregorianCalendar(2021, Calendar.FEBRUARY, 12).getTime()); - TestData data3 = new TestData(new GregorianCalendar(2022, Calendar.MARCH, 13).getTime()); - TestData data4 = new TestData(new GregorianCalendar(2023, Calendar.APRIL, 14).getTime()); - TestData data5 = new TestData(new GregorianCalendar(2024, Calendar.MAY, 15).getTime()); - TestData data6 = new TestData(new GregorianCalendar(2025, Calendar.JUNE, 16).getTime()); - - ObjectRepository repository = db.getRepository(TestData.class); - repository.insert(data1, data2, data3, data4, data5, data6); - - Cursor cursor = repository.find(where("age").between( - new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), - new GregorianCalendar(2025, Calendar.JUNE, 16).getTime())); - assertEquals(cursor.size(), 6); - - cursor = repository.find(where("age").between( - new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), - new GregorianCalendar(2025, Calendar.JUNE, 16).getTime(), false)); - assertEquals(cursor.size(), 4); - - cursor = repository.find(where("age").between( - new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), - new GregorianCalendar(2025, Calendar.JUNE, 16).getTime(), false, true)); - assertEquals(cursor.size(), 5); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/UnAnnotatedObjectTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/UnAnnotatedObjectTest.java deleted file mode 100644 index b6ce0f421..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/UnAnnotatedObjectTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository; - - -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapdb.repository.data.ClassA; -import org.dizitart.no2.mapdb.repository.data.ClassC; -import org.dizitart.no2.repository.Cursor; -import org.junit.Test; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -/** - * @author Anindya Chatterjee. - */ -public class UnAnnotatedObjectTest extends BaseObjectRepositoryTest { - - @Test - @SuppressWarnings("unchecked") - public void testFind() { - Cursor cursor = aObjectRepository.find(); - assertEquals(cursor.size(), 10); - assertFalse(cursor.isEmpty()); - - IndexOptions indexOptions = new IndexOptions(); - indexOptions.setIndexType(IndexType.Unique); - aObjectRepository.createIndex("b.number", indexOptions); - - cursor = aObjectRepository.find(where("b.number").eq(160).not()). - sort("b.number", SortOrder.Ascending).skipLimit(0, 10); - - System.out.println("Available - " + !cursor.isEmpty()); - System.out.println("Total Size - " + cursor.size()); - - Iterable findRecord = cursor.project(ClassA.class); - for (ClassA classA : findRecord) { - System.out.println(classA); - } - - cursor = aObjectRepository.find(where("b.number").eq(160).not()). - sort("b.number", SortOrder.Descending).skipLimit(2, 7); - - System.out.println("Available - " + !cursor.isEmpty()); - System.out.println("Total Size - " + cursor.size()); - - findRecord = cursor.project(ClassA.class); - for (ClassA classA : findRecord) { - System.out.println(classA); - } - - cursor = cObjectRepository.find(where("id").gt(900)). - sort("id", SortOrder.Descending).skipLimit(2, 7); - System.out.println("Available - " + !cursor.isEmpty()); - System.out.println("Total Size - " + cursor.size()); - - Iterable findRecordC = cursor.project(ClassC.class); - for (ClassC classC : findRecordC) { - System.out.println(classC); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/UniversalTextTokenizerTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/UniversalTextTokenizerTest.java deleted file mode 100644 index 6637407d2..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/UniversalTextTokenizerTest.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.index.NitriteTextIndexer; -import org.dizitart.no2.index.fulltext.Languages; -import org.dizitart.no2.index.fulltext.UniversalTextTokenizer; -import org.dizitart.no2.mapdb.MapDBModule; -import org.dizitart.no2.mapdb.MapDBModuleBuilder; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.Cursor; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; - -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.mapdb.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.module.NitriteModule.module; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -/** - * @author Anindya Chatterjee - */ -public class UniversalTextTokenizerTest extends BaseObjectRepositoryTest { - private final String fileName = getRandomTempDbFile(); - private ObjectRepository textRepository; - - @Before - @Override - public void setUp() { - openDb(); - - textRepository = db.getRepository(TextData.class); - - for (int i = 0; i < 10; i++) { - TextData data = new TextData(); - data.id = i; - if (i % 2 == 0) { - data.text = "তারা বলল, “এস আমরা আমাদের জন্যে এক বড় শহর বানাই| আর এমন একটি উঁচু স্তম্ভ বানাই " + - "যা আকাশ স্পর্শ করবে| তাহলে আমরা বিখ্যাত হব এবং এটা আমাদের এক সঙ্গে ধরে রাখবে| সারা পৃথিবীতে " + - "আমরা ছড়িয়ে থাকব না|”"; - } else if (i % 3 == 0) { - data.text = "部汁楽示時葉没式将場参右属。覧観将者雄日語山銀玉襲政著約域費。新意虫跡更味株付安署審完顔団。" + - "困更表転定一史賀面政巣迎文学豊税乗。白間接特時京転閉務講封新内。側流効表害場測投活聞秀職探画労。" + - "福川順式極木注美込行警検直性禁遅。土一詳非物質紙姿漢人内池銀周街躍澹二。平討聞述並時全経詳業映回作朝送恵時。"; - } else if (i % 5 == 0) { - data.text = " أقبل لسفن العالم، في أما, بـ بال أملاً الثالث،. الذود بالرّد الثالث، مع" + - " قام, كردة الضغوط الإمداد أن وصل. ٠٨٠٤ عُقر انتباه يكن قد, أن زهاء وفنلندا بال. لان ما يقوم المعاهدات," + - " بـ بخطوط استعملت عدد. صفحة لفشل ولاتّساع لم قام, في مكثّفة الكونجرس جعل, الثالث، واقتصار دون ان.\n"; - } else { - data.text = "Lorem ipsum dolor sit amet, nobis audire perpetua eu sea. Te semper causae " + - "efficiantur per. Qui affert dolorum at. Mel tale constituto interesset in."; - } - textRepository.insert(data); - } - } - - @After - @Override - public void clear() throws IOException { - if (textRepository != null && !textRepository.isDropped()) { - textRepository.remove(ALL); - } - - if (db != null) { - db.commit(); - db.close(); - } - - if (!inMemory) { - Files.delete(Paths.get(fileName)); - } - } - - private void openDb() { - MapDBModuleBuilder builder = MapDBModule.withConfig(); - - if (!inMemory) { - builder.filePath(fileName); - } - - MapDBModule storeModule = builder.build(); - NitriteBuilder nitriteBuilder = Nitrite.builder() - .fieldSeparator(".") - .loadModule(storeModule); - - UniversalTextTokenizer tokenizer; - if (isProtected) { - tokenizer = new UniversalTextTokenizer(Languages.Bengali, Languages.Chinese, Languages.English); - } else { - tokenizer = new UniversalTextTokenizer(Languages.ALL); - } - nitriteBuilder.loadModule(module(new NitriteTextIndexer(tokenizer))); - - if (isProtected) { - db = nitriteBuilder.openOrCreate("test-user", "test-password"); - } else { - db = nitriteBuilder.openOrCreate(); - } - } - - @Test - public void testUniversalFullTextIndexing() { - Cursor cursor = textRepository.find(where("text").text("Lorem")); - assertEquals(cursor.size(), 2); - for (TextData data : cursor) { - System.out.println("Id for English text -> " + data.id); - if (data.id % 2 == 0 || data.id % 3 == 0 || data.id % 5 == 0) { - fail(); - } - } - - cursor = textRepository.find(where("text").text("শহর")); - assertEquals(cursor.size(), 5); - for (TextData data : cursor) { - System.out.println("Id for Bengali text -> " + data.id); - if (data.id % 2 != 0) { - fail(); - } - } - - cursor = textRepository.find(where("text").text("転閉")); - assertEquals(cursor.size(), 0); - cursor = textRepository.find(where("text").text("*転閉*")); - assertEquals(cursor.size(), 2); - for (TextData data : cursor) { - System.out.println("Id for Chinese text -> " + data.id); - if (data.id % 3 != 0) { - fail(); - } - } - - cursor = textRepository.find(where("text").text("أقبل")); - if (isProtected) { - assertEquals(cursor.size(), 1); - for (TextData data : cursor) { - System.out.println("Id for Arabic text -> " + data.id); - if (data.id % 5 != 0) { - fail(); - } - } - } else { - // أقبل eliminated as stop word - assertEquals(cursor.size(), 0); - } - } - - @Indices( - @Index(value = "text", type = IndexType.Fulltext) - ) - public static class TextData implements Mappable { - public int id; - public String text; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("id", id) - .put("text", text); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Integer.class); - text = document.get("text", String.class); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ChildClass.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ChildClass.java deleted file mode 100644 index a48918c33..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ChildClass.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.InheritIndices; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@InheritIndices -public class ChildClass extends ParentClass { - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return super.write(mapper).put("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - super.read(mapper, document); - name = document.get("name", String.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ClassA.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ClassA.java deleted file mode 100644 index 30e2c4c74..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ClassA.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.util.UUID; - -@EqualsAndHashCode -@ToString -public class ClassA implements Mappable { - @Getter - @Setter - private ClassB classB; - @Getter - @Setter - private UUID uid; - @Getter - @Setter - private String string; - @Getter - @Setter - private byte[] blob; - - public static ClassA create(int seed) { - ClassB classB = ClassB.create(seed); - ClassA classA = new ClassA(); - classA.classB = classB; - classA.uid = new UUID(seed, seed + 50); - classA.string = Integer.toHexString(seed); - classA.blob = new byte[]{(byte) seed}; - return classA; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("classB", classB != null ? classB.write(mapper) : null) - .put("uid", uid) - .put("string", string) - .put("blob", blob); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - if (document.get("classB") != null) { - classB = new ClassB(); - classB.read(mapper, document.get("classB", Document.class)); - } - uid = document.get("uid", UUID.class); - string = document.get("string", String.class); - blob = document.get("blob", byte[].class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ClassB.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ClassB.java deleted file mode 100644 index 0bf49ba01..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ClassB.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -@EqualsAndHashCode -@ToString -class ClassB implements Comparable, Mappable { - @Getter - @Setter - private int number; - @Getter - @Setter - private String text; - - static ClassB create(int seed) { - ClassB classB = new ClassB(); - classB.setNumber(seed + 100); - classB.setText(Integer.toBinaryString(seed)); - return classB; - } - - @Override - public int compareTo(ClassB o) { - return Integer.compare(number, o.number); - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("number", number) - .put("text", text); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - number = document.get("number", Integer.class); - text = document.get("text", String.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ClassC.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ClassC.java deleted file mode 100644 index 4dff3f804..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ClassC.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -@EqualsAndHashCode -@ToString -public class ClassC implements Mappable { - @Getter - @Setter - private long id; - @Getter - @Setter - private double digit; - @Getter - @Setter - private ClassA parent; - - public static ClassC create(int seed) { - ClassC classC = new ClassC(); - classC.id = seed * 5000; - classC.digit = seed * 69.65; - classC.parent = ClassA.create(seed); - return classC; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("id", id) - .put("digit", digit) - .put("parent", parent != null ? parent.write(mapper) : null); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Long.class); - digit = document.get("digit", Double.class); - if (document.get("parent") != null) { - parent = new ClassA(); - parent.read(mapper, document.get("parent", Document.class)); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/Company.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/Company.java deleted file mode 100644 index d06abd742..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/Company.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; - -import java.io.Serializable; -import java.util.Date; -import java.util.List; -import java.util.Map; - -/** - * @author Anindya Chatterjee. - */ -@ToString -@EqualsAndHashCode -@Indices({ - @Index(value = "companyName") -}) -public class Company implements Serializable, Mappable { - @Id - @Getter - @Setter - private Long companyId; - - @Getter - @Setter - private String companyName; - - @Getter - @Setter - private Date dateCreated; - - @Getter - @Setter - private List departments; - - @Getter - @Setter - private Map> employeeRecord; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("companyId", companyId) - .put("companyName", companyName) - .put("dateCreated", dateCreated) - .put("departments", departments) - .put("employeeRecord", employeeRecord); - } - - @Override - @SuppressWarnings("unchecked") - public void read(NitriteMapper mapper, Document document) { - companyId = document.get("companyId", Long.class); - companyName = document.get("companyName", String.class); - dateCreated = document.get("dateCreated", Date.class); - departments = document.get("departments", List.class); - employeeRecord = document.get("employeeRecord", Map.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/DataGenerator.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/DataGenerator.java deleted file mode 100644 index 49b2631be..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/DataGenerator.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import com.google.common.collect.Lists; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @author Anindya Chatterjee. - */ -public class DataGenerator { - private DataGenerator() {} - private static final Random random = new Random(System.currentTimeMillis()); - private static final AtomicInteger counter = new AtomicInteger(random.nextInt()); - - public static Company generateCompanyRecord() { - Company company = new Company(); - company.setCompanyId(System.nanoTime() + counter.incrementAndGet()); - company.setCompanyName(randomCompanyName()); - company.setDateCreated(randomDate()); - List departments = departments(); - company.setDepartments(departments); - - Map> employeeRecord = new HashMap<>(); - for (String department : departments) { - employeeRecord.put(department, - generateEmployeeRecords(company, random.nextInt(20))); - } - company.setEmployeeRecord(employeeRecord); - return company; - } - - private static List generateEmployeeRecords(Company company, int count) { - List employeeList = new ArrayList<>(); - for (int i = 0; i < count; i++) { - Employee employee = generateEmployee(); - employee.setCompany(company); - employeeList.add(employee); - } - return employeeList; - } - - public static Employee generateEmployee() { - Employee employee = new Employee(); - employee.setEmpId(System.nanoTime() + counter.incrementAndGet()); - employee.setJoinDate(randomDate()); - employee.setAddress(UUID.randomUUID().toString().replace('-', ' ')); - - byte[] blob = new byte[random.nextInt(8000)]; - random.nextBytes(blob); - employee.setBlob(blob); - employee.setEmployeeNote(randomNote()); - - return employee; - } - - private static Date randomDate() { - return new Date(-946771200000L + - (Math.abs(random.nextLong()) % (70L * 365 * 24 * 60 * 60 * 1000))); - } - - public static Note randomNote() { - InputStream inputStream = ClassLoader.getSystemResourceAsStream("test.text"); - - assert inputStream != null; - try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) { - String strLine; - long line = random.nextInt(49); - int count = 0; - while ((strLine = br.readLine()) != null) { - if (count == line) { - Note note = new Note(); - note.setNoteId(line); - note.setText(strLine); - return note; - } - count++; - } - } catch (IOException e) { - // ignore - } - // ignore - return null; - } - - private static String randomCompanyName() { - InputStream inputStream = ClassLoader.getSystemResourceAsStream("english.stop"); - - assert inputStream != null; - try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) { - String strLine; - int line = random.nextInt(570); - int count = 0; - while ((strLine = br.readLine()) != null) { - if (count == line) { - return strLine + System.nanoTime() + " inc."; - } - count++; - } - } catch (IOException e) { - // ignore - } - // ignore - return null; - } - - private static List departments() { - return Lists.newArrayList( - "dev", - "hr", - "qa", - "dev-ops", - "sales", - "marketing", - "design", - "support" - ); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ElemMatch.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ElemMatch.java deleted file mode 100644 index 80187cc2b..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ElemMatch.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author Anindya Chatterjee - */ -@Data -public class ElemMatch implements Mappable { - private long id; - private String[] strArray; - private ProductScore[] productScores; - - @Override - public Document write(NitriteMapper mapper) { - List list = new ArrayList<>(); - if (productScores != null) { - for (ProductScore productScore : productScores) { - Document document = productScore.write(mapper); - list.add(document); - } - } - - return Document.createDocument("id", id) - .put("strArray", strArray) - .put("productScores", list); - } - - @Override - @SuppressWarnings("unchecked") - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Long.class); - strArray = document.get("strArray", String[].class); - List list = document.get("productScores", List.class); - if (list != null) { - productScores = new ProductScore[list.size()]; - for (int i = 0; i < list.size(); i++) { - productScores[i] = new ProductScore(); - productScores[i].read(mapper, list.get(i)); - } - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/Employee.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/Employee.java deleted file mode 100644 index a1323e0d6..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/Employee.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; - -import java.io.Serializable; -import java.util.Date; - -/** - * @author Anindya Chatterjee. - */ -@ToString -@EqualsAndHashCode -@Index(value = "joinDate", type = IndexType.NonUnique) -@Index(value = "address", type = IndexType.Fulltext) -@Index(value = "employeeNote.text", type = IndexType.Fulltext) -public class Employee implements Serializable, Mappable { - @Id - @Getter - @Setter - private Long empId; - - @Getter - @Setter - private Date joinDate; - - @Getter - @Setter - private String address; - - @Getter - @Setter - private transient Company company; - - @Getter - @Setter - private byte[] blob; - - @Getter - @Setter - private Note employeeNote; - - public Employee() { - } - - public Employee(Employee copy) { - empId = copy.empId; - joinDate = copy.joinDate; - address = copy.address; - company = copy.company; - blob = copy.blob; - employeeNote = copy.employeeNote; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("empId", empId) - .put("joinDate", joinDate) - .put("address", address) - .put("blob", blob) - .put("employeeNote", employeeNote != null ? employeeNote.write(mapper) : null); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - empId = document.get("empId", Long.class); - joinDate = document.get("joinDate", Date.class); - address = document.get("address", String.class); - blob = document.get("blob", byte[].class); - - if (document.get("employeeNote") != null) { - employeeNote = new Note(); - employeeNote.read(mapper, document.get("employeeNote", Document.class)); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/Note.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/Note.java deleted file mode 100644 index c9e6fde60..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/Note.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.io.Serializable; - -/** - * @author Anindya Chatterjee. - */ -@EqualsAndHashCode -public class Note implements Serializable, Mappable { - @Getter - @Setter - private Long noteId; - @Getter - @Setter - private String text; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument().put("noteId", noteId).put("text", text); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - noteId = document.get("noteId", Long.class); - text = document.get("text", String.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ParentClass.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ParentClass.java deleted file mode 100644 index e6cc7fddd..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ParentClass.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; - -import java.util.Date; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@Index(value = "date") -public class ParentClass extends SuperDuperClass { - @Id - protected Long id; - private Date date; - - @Override - public Document write(NitriteMapper mapper) { - return super.write(mapper) - .put("id", id) - .put("date", date); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - super.read(mapper, document); - id = document.get("id", Long.class); - date = document.get("date", Date.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/PersonEntity.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/PersonEntity.java deleted file mode 100644 index c1c85f3f9..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/PersonEntity.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Entity; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; - -import java.util.Date; -import java.util.UUID; - -/** - * @author Anindya Chatterjee - */ -@Data -@Entity(value = "MyPerson", indices = { - @Index(value = "name", type = IndexType.Fulltext), - @Index(value = "status", type = IndexType.NonUnique) -}) -public class PersonEntity implements Mappable { - @Id - private String uuid; - private String name; - private String status; - private PersonEntity friend; - private Date dateCreated; - - public PersonEntity() { - this.uuid = UUID.randomUUID().toString(); - this.dateCreated = new Date(); - } - - public PersonEntity(String name) { - this.uuid = UUID.randomUUID().toString(); - this.name = name; - this.dateCreated = new Date(); - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("uuid", uuid) - .put("name", name) - .put("status", status) - .put("friend", friend != null ? friend.write(mapper) : null) - .put("dateCreated", dateCreated); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - if (document != null) { - uuid = document.get("uuid", String.class); - name = document.get("name", String.class); - status = document.get("status", String.class); - dateCreated = document.get("dateCreated", Date.class); - friend = new PersonEntity(); - friend.read(mapper, document.get("friend", Document.class)); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ProductScore.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ProductScore.java deleted file mode 100644 index 52e522008..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/ProductScore.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -public class ProductScore implements Mappable { - private String product; - private int score; - - public ProductScore() { - } - - public ProductScore(String product, int score) { - this.product = product; - this.score = score; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("product", product) - .put("score", score); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - product = document.get("product", String.class); - score = document.get("score", Integer.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/RepeatableIndexTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/RepeatableIndexTest.java deleted file mode 100644 index 78686aa6e..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/RepeatableIndexTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Index; - -/** - * @author Anindya Chatterjee - */ -@Data -@Index(value = "firstName") -@Index(value = "age", type = IndexType.NonUnique) -@Index(value = "lastName", type = IndexType.Fulltext) -public class RepeatableIndexTest implements Mappable { - private String firstName; - private Integer age; - private String lastName; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("firstName", firstName) - .put("age", age) - .put("lastName", lastName); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - firstName = document.get("firstName", String.class); - age = document.get("age", Integer.class); - lastName = document.get("lastName", String.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/StressRecord.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/StressRecord.java deleted file mode 100644 index 8523e9e36..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/StressRecord.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class StressRecord implements Mappable { - private String firstName; - private boolean processed; - private String lastName; - private boolean failed; - private String notes; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument().put("firstName", firstName) - .put("processed", processed) - .put("lastName", lastName) - .put("failed", failed) - .put("notes", notes); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - firstName = document.get("firstName", String.class); - processed = document.get("processed", Boolean.class); - lastName = document.get("lastName", String.class); - failed = document.get("failed", Boolean.class); - notes = document.get("notes", String.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/SubEmployee.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/SubEmployee.java deleted file mode 100644 index 3506e1b9d..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/SubEmployee.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.util.Date; - -/** - * @author Anindya Chatterjee. - */ -@EqualsAndHashCode -public class SubEmployee implements Mappable { - @Getter - @Setter - private Long empId; - - @Getter - @Setter - private Date joinDate; - - @Getter - @Setter - private String address; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("empId", empId) - .put("joinDate", joinDate) - .put("address", address); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - empId = document.get("empId", Long.class); - joinDate = document.get("joinDate", Date.class); - address = document.get("address", String.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/SuperDuperClass.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/SuperDuperClass.java deleted file mode 100644 index 7be25aba7..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/SuperDuperClass.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Index; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@Index(value = "text", type = IndexType.Fulltext) -public class SuperDuperClass implements Mappable { - private String text; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("text", text); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - text = document.get("text", String.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithCircularReference.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithCircularReference.java deleted file mode 100644 index a08a0ac76..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithCircularReference.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.Getter; -import lombok.Setter; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithCircularReference { - private String name; - private WithCircularReference parent; -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithClassField.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithClassField.java deleted file mode 100644 index fc3cdb09b..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithClassField.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithClassField implements Mappable { - @Id - private String name; - private Class clazz; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name) - .put("clazz", clazz); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - clazz = document.get("clazz", Class.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithCustomConstructor.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithCustomConstructor.java deleted file mode 100644 index 93dbb8b55..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithCustomConstructor.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.Getter; -import lombok.Setter; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithCustomConstructor { - private String name; - private long number; - - public WithCustomConstructor(String name, long number) { - this.name = name; - this.number = number; - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithDateId.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithDateId.java deleted file mode 100644 index 9e37fbee8..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithDateId.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.util.Date; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@EqualsAndHashCode -public class WithDateId implements Mappable { - private Date id; - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name) - .put("id", id); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - id = document.get("id", Date.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithEmptyStringId.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithEmptyStringId.java deleted file mode 100644 index 8d0f42320..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithEmptyStringId.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithEmptyStringId implements Mappable { - @Id - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithFinalField.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithFinalField.java deleted file mode 100644 index f74583d35..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithFinalField.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.exceptions.ObjectMappingException; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; - -/** - * @author Anindya Chatterjee. - */ -@Getter -public class WithFinalField implements Mappable { - private final long number; - @Setter - private String name; - - public WithFinalField() { - number = 2; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("name", name) - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - try { - Field field = getClass().getDeclaredField("number"); - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); - field.set(this, document.get("number", Long.class)); - } catch (Exception e) { - throw new ObjectMappingException("failed to set value"); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithNitriteId.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithNitriteId.java deleted file mode 100644 index 182215ac5..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithNitriteId.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee - */ -@Data -public class WithNitriteId implements Mappable { - @Id - public NitriteId idField; - public String name; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("idField", idField) - .put("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - idField = document.get("idField", NitriteId.class); - name = document.get("name", String.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithNullId.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithNullId.java deleted file mode 100644 index 6ccf891b8..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithNullId.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithNullId implements Mappable { - @Id - private String name; - private long number; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("name", name) - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - number = document.get("number", Long.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithObjectId.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithObjectId.java deleted file mode 100644 index 9505b57c7..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithObjectId.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithObjectId implements Mappable { - @Id - private WithOutId withOutId; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("withOutId", withOutId); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - withOutId = document.get("withOutId", WithOutId.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithOutGetterSetter.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithOutGetterSetter.java deleted file mode 100644 index ef755e1a7..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithOutGetterSetter.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.EqualsAndHashCode; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@EqualsAndHashCode -public class WithOutGetterSetter implements Mappable { - private String name; - private long number; - - public WithOutGetterSetter() { - name = "test"; - number = 2; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name) - .put("number", number); - - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - number = document.get("number", Long.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithOutId.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithOutId.java deleted file mode 100644 index 06ba40ebc..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithOutId.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithOutId implements Comparable, Mappable { - private String name; - private long number; - - @Override - public int compareTo(WithOutId o) { - return Long.compare(number, o.number); - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("name", name) - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - number = document.get("number", Long.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithPrivateConstructor.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithPrivateConstructor.java deleted file mode 100644 index d65cf7c34..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithPrivateConstructor.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.EqualsAndHashCode; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@EqualsAndHashCode -public class WithPrivateConstructor implements Mappable { - private String name; - private long number; - - private WithPrivateConstructor() { - name = "test"; - number = 2; - } - - public static WithPrivateConstructor create(final String name, final long number) { - WithPrivateConstructor obj = new WithPrivateConstructor(); - obj.number = number; - obj.name = name; - return obj; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name) - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - number = document.get("number", Long.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithPublicField.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithPublicField.java deleted file mode 100644 index 33b45fe2d..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithPublicField.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -public class WithPublicField implements Mappable { - @Id - public String name; - public long number; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name) - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - number = document.get("number", Long.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithTransientField.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithTransientField.java deleted file mode 100644 index 781b7c650..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/repository/data/WithTransientField.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithTransientField implements Mappable { - private transient String name; - @Id - private long number; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - number = document.get("number", Long.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/transaction/TransactionCollectionTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/transaction/TransactionCollectionTest.java deleted file mode 100644 index db5dc24be..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/transaction/TransactionCollectionTest.java +++ /dev/null @@ -1,772 +0,0 @@ -package org.dizitart.no2.mapdb.transaction; - -import com.github.javafaker.Faker; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.TransactionException; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapdb.BaseCollectionTest; -import org.dizitart.no2.transaction.Session; -import org.dizitart.no2.transaction.Transaction; -import org.junit.Test; - -import java.util.*; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.collection.UpdateOptions.updateOptions; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -public class TransactionCollectionTest extends BaseCollectionTest { - - @Test - public void testCommitInsert() { - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - - Document document = createDocument("firstName", "John"); - txCol.insert(document); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); - assertNotEquals(collection.find(where("firstName").eq("John")).size(), 1); - - transaction.commit(); - - assertEquals(collection.find(where("firstName").eq("John")).size(), 1); - } - } - } - - @Test - public void testRollbackInsert() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - NitriteCollection txCol = transaction.getCollection("test"); - - Document document = createDocument("firstName", "John"); - Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); - txCol.insert(document); - txCol.insert(document2); - - // just to create UniqueConstraintViolation for rollback - collection.insert(createDocument("firstName", "Jane")); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertNotEquals(collection.find(where("firstName").eq("John")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - } - } - } - - @Test - public void testCommitUpdate() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - document.put("lastName", "Doe"); - - txCol.update(where("firstName").eq("John"), document, updateOptions(true)); - - assertEquals(txCol.find(where("lastName").eq("Doe")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - - transaction.commit(); - - assertEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - } - } - } - - @Test - public void testRollbackUpdate() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.insert(createDocument("firstName", "Jane")); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - NitriteCollection txCol = transaction.getCollection("test"); - - Document document = createDocument("firstName", "John"); - Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); - txCol.update(where("firstName").eq("Jane"), document2); - txCol.insert(document); - - // just to create UniqueConstraintViolation for rollback - collection.insert(createDocument("firstName", "John")); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); - assertEquals(txCol.find(where("lastName").eq("Doe")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(collection.find(where("firstName").eq("Jane")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - } - } - } - - @Test - public void testCommitRemove() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - - txCol.remove(where("firstName").eq("John")); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 0); - assertEquals(collection.find(where("firstName").eq("John")).size(), 1); - - transaction.commit(); - - assertEquals(collection.find(where("firstName").eq("John")).size(), 0); - } - } - } - - @Test - public void testRollbackRemove() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - - txCol.remove(where("firstName").eq("John")); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 0); - assertEquals(collection.find(where("firstName").eq("John")).size(), 1); - - txCol.insert(createDocument("firstName", "Jane")); - collection.insert(createDocument("firstName", "Jane")); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(collection.find(where("firstName").eq("John")).size(), 1); - assertEquals(collection.find(where("firstName").eq("Jane")).size(), 1); - } - } - } - - @Test - public void testCommitCreateIndex() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - txCol.createIndex("firstName", indexOptions(IndexType.Fulltext)); - - assertTrue(txCol.hasIndex("firstName")); - assertFalse(collection.hasIndex("firstName")); - - transaction.commit(); - - assertTrue(collection.hasIndex("firstName")); - } - } - } - - @Test - public void testRollbackCreateIndex() { - Document document = createDocument("firstName", "John"); - Document document2 = createDocument("firstName", "Jane"); - collection.insert(document); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - - txCol.createIndex("firstName", indexOptions(IndexType.Unique)); - - assertTrue(txCol.hasIndex("firstName")); - assertFalse(collection.hasIndex("firstName")); - - txCol.insert(document2); - collection.insert(document2); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertFalse(collection.hasIndex("firstName")); - } - } - } - - @Test - public void testCommitClear() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - txCol.clear(); - - assertEquals(0, txCol.size()); - assertEquals(1, collection.size()); - - transaction.commit(); - - assertEquals(0, collection.size()); - } - } - } - - @Test - public void testRollbackClear() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - Document document = createDocument("firstName", "John"); - Document document2 = createDocument("firstName", "Jane"); - collection.insert(document); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - - txCol.clear(); - - assertEquals(0, txCol.size()); - assertEquals(1, collection.size()); - - txCol.insert(document2); - collection.insert(document2); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(2, collection.size()); - } - } - } - - @Test - public void testCommitDropIndex() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - txCol.dropIndex("firstName"); - - assertFalse(txCol.hasIndex("firstName")); - assertTrue(collection.hasIndex("firstName")); - - transaction.commit(); - - assertFalse(collection.hasIndex("firstName")); - } - } - } - - @Test - public void testRollbackDropIndex() { - Document document = createDocument("firstName", "John").put("lastName", "Doe"); - Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); - collection.insert(document); - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - txCol.dropIndex("lastName"); - - assertFalse(txCol.hasIndex("lastName")); - assertTrue(collection.hasIndex("lastName")); - - txCol.insert(document2); - collection.insert(document2); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertTrue(collection.hasIndex("lastName")); - } - } - } - - @Test - public void testCommitDropAllIndices() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("lastName", indexOptions(IndexType.Unique)); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - txCol.dropAllIndices(); - - assertFalse(txCol.hasIndex("firstName")); - assertFalse(txCol.hasIndex("lastName")); - assertTrue(collection.hasIndex("firstName")); - assertTrue(collection.hasIndex("lastName")); - - transaction.commit(); - - assertFalse(collection.hasIndex("firstName")); - assertFalse(collection.hasIndex("lastName")); - } - } - } - - @Test - public void testRollbackDropAllIndices() { - Document document = createDocument("firstName", "John").put("lastName", "Doe"); - collection.insert(document); - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - txCol.dropAllIndices(); - - assertFalse(txCol.hasIndex("firstName")); - assertFalse(txCol.hasIndex("lastName")); - assertTrue(collection.hasIndex("firstName")); - assertTrue(collection.hasIndex("lastName")); - - txCol.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); - collection.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertTrue(collection.hasIndex("firstName")); - assertTrue(collection.hasIndex("lastName")); - } - } - } - - @Test - public void testCommitDropCollection() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - txCol.drop(); - - boolean expectedException = false; - try { - assertEquals(0, txCol.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - assertEquals(1, collection.size()); - - transaction.commit(); - - expectedException = false; - try { - assertEquals(0, collection.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - } - } - } - - @Test - public void testRollbackDropCollection() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - - txCol.drop(); - - boolean expectedException = false; - try { - assertEquals(0, txCol.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - assertEquals(1, collection.size()); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(1, collection.size()); - } - } - } - - @Test - public void testCommitSetAttribute() { - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - - Attributes attributes = new Attributes(); - attributes.setAttributes(Collections.singletonMap("key", "value")); - txCol.setAttributes(attributes); - - assertNull(collection.getAttributes()); - - transaction.commit(); - - assertEquals("value", collection.getAttributes().get("key")); - } - } - } - - @Test - public void testRollbackSetAttribute() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - NitriteCollection txCol = transaction.getCollection("test"); - - Attributes attributes = new Attributes(); - Map map = new HashMap<>(); - map.put("key", "value"); - attributes.setAttributes(map); - txCol.setAttributes(attributes); - - txCol.insert(createDocument("firstName", "John")); - txCol.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); - - assertNull(collection.getAttributes()); - - // just to create UniqueConstraintViolation for rollback - collection.insert(createDocument("firstName", "Jane")); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertNull(collection.getAttributes().get("key")); - } - } - } - - @Test - public void testConcurrentInsertAndRemove() { - NitriteCollection collection = db.getCollection("test"); - collection.createIndex("firstName", indexOptions(IndexType.NonUnique)); - collection.createIndex("id", indexOptions(IndexType.Unique)); - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - final long fi = i; - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - NitriteCollection txCol = transaction.getCollection("test"); - - for (int j = 0; j < 10; j++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("lastName", faker.name().lastName()) - .put("id", j + (fi * 10)); - txCol.insert(document); - } - - txCol.remove(where("id").eq(2 + (fi * 10))); - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(90, collection.size()); - } - } - - @Test - public void testConcurrentInsert() { - NitriteCollection collection = db.getCollection("test"); - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - NitriteCollection txCol = transaction.getCollection("test"); - - for (int j = 0; j < 10; j++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("lastName", faker.name().lastName()); - txCol.insert(document); - } - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(100, collection.size()); - } - } - - @Test - public void testConcurrentUpdate() { - NitriteCollection collection = db.getCollection("test"); - for (int i = 0; i < 10; i++) { - Document document = createDocument("id", i); - collection.insert(document); - } - - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - NitriteCollection txCol = transaction.getCollection("test"); - - for (int j = 0; j < 10; j++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("lastName", faker.name().lastName()) - .put("id", j); - txCol.update(where("id").eq(j), document, updateOptions(true)); - } - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(10, collection.size()); - } - } - - @Test - public void testTransactionOnDifferentCollections() { - NitriteCollection col1 = db.getCollection("test1"); - NitriteCollection col2 = db.getCollection("test2"); - NitriteCollection col3 = db.getCollection("test3"); - col3.createIndex("id", indexOptions(IndexType.Unique)); - - Faker faker = new Faker(); - - try(Session session = db.createSession()) { - Transaction transaction = session.beginTransaction(); - - NitriteCollection test1 = transaction.getCollection("test1"); - NitriteCollection test2 = transaction.getCollection("test2"); - NitriteCollection test3 = transaction.getCollection("test3"); - - for (int i = 0; i < 10; i++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", i); - test1.insert(document); - - document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 10); - test2.insert(document); - - document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 20); - test3.insert(document); - } - - assertEquals(test1.size(), 10); - assertEquals(test2.size(), 10); - assertEquals(test3.size(), 10); - - assertEquals(col1.size(), 0); - assertEquals(col2.size(), 0); - assertEquals(col3.size(), 0); - - transaction.commit(); - - assertEquals(col1.size(), 10); - assertEquals(col2.size(), 10); - assertEquals(col3.size(), 10); - } - - - Transaction transaction = null; - try (Session session = db.createSession()) { - transaction = session.beginTransaction(); - - NitriteCollection test1 = transaction.getCollection("test1"); - NitriteCollection test2 = transaction.getCollection("test2"); - NitriteCollection test3 = transaction.getCollection("test3"); - - for (int i = 0; i < 10; i++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 30); - test1.insert(document); - - document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 40); - test2.insert(document); - - document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 50); - test3.insert(document); - } - - assertEquals(test1.size(), 20); - assertEquals(test2.size(), 20); - assertEquals(test3.size(), 20); - - assertEquals(col1.size(), 10); - assertEquals(col2.size(), 10); - assertEquals(col3.size(), 10); - - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", 52); - col3.insert(document); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - - assertEquals(col1.size(), 10); - assertEquals(col2.size(), 10); - assertEquals(col3.size(), 11); // last document added - } - } - - @Test(expected = TransactionException.class) - public void testFailureOnClosedTransaction() { - try(Session session = db.createSession()) { - Transaction transaction = session.beginTransaction(); - NitriteCollection col = transaction.getCollection("test"); - col.insert(createDocument("id", 1)); - transaction.commit(); - - col.insert(createDocument("id", 2)); - fail(); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/transaction/TransactionRepositoryTest.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/transaction/TransactionRepositoryTest.java deleted file mode 100644 index f0aa5cfaa..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/transaction/TransactionRepositoryTest.java +++ /dev/null @@ -1,810 +0,0 @@ -package org.dizitart.no2.mapdb.transaction; - -import com.github.javafaker.Faker; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.TransactionException; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapdb.repository.BaseObjectRepositoryTest; -import org.dizitart.no2.mapdb.repository.data.SubEmployee; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.transaction.Session; -import org.dizitart.no2.transaction.Transaction; -import org.junit.Test; - -import java.util.*; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -public class TransactionRepositoryTest extends BaseObjectRepositoryTest { - - @Test - public void testCommitInsert() { - ObjectRepository repository = db.getRepository(TxData.class); - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - TxData txData1 = new TxData(); - txData1.setId(1L); - txData1.setName("John"); - - txRepo.insert(txData1); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 1); - assertNotEquals(repository.find(where("name").eq("John")).size(), 1); - - transaction.commit(); - - assertEquals(repository.find(where("name").eq("John")).size(), 1); - } - } - } - - @Test - public void testRollbackInsert() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - TxData txData1 = new TxData(); - txData1.setId(1L); - txData1.setName("John"); - - TxData txData2 = new TxData(); - txData2.setId(2L); - txData2.setName("Jane"); - - txRepo.insert(txData1, txData2); - - txData2.setName("Molly"); - repository.insert(txData2); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 1); - assertEquals(repository.find(where("name").eq("John")).size(), 0); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(repository.find(where("name").eq("John")).size(), 0); - assertEquals(repository.find(where("name").eq("Molly")).size(), 1); - } - } - } - - @Test - public void testCommitUpdate() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(new TxData(1L, "John")); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - TxData txData1 = new TxData(1L, "Jane"); - txRepo.update(txData1, true); - - assertEquals(txRepo.find(where("name").eq("Jane")).size(), 1); - assertNotEquals(repository.find(where("name").eq("Jane")).size(), 1); - - transaction.commit(); - - assertEquals(repository.find(where("name").eq("Jane")).size(), 1); - } - } - } - - @Test - public void testRollbackUpdate() { - ObjectRepository repository = db.getRepository(TxData.class, "rollback"); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(new TxData(1L, "Jane")); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - ObjectRepository txRepo = transaction.getRepository(TxData.class, "rollback"); - - TxData txData1 = new TxData(); - txData1.setId(2L); - txData1.setName("John"); - - TxData txData2 = new TxData(); - txData2.setId(1L); - txData2.setName("Jane Doe"); - txRepo.update(txData2); - txRepo.insert(txData1); - - // just to create UniqueConstraintViolation for rollback - repository.insert(txData1); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 1); - assertEquals(txRepo.find(where("name").eq("Jane Doe")).size(), 1); - assertNotEquals(repository.find(where("name").eq("Jane Doe")).size(), 1); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(repository.find(where("name").eq("Jane")).size(), 1); - assertNotEquals(repository.find(where("name").eq("Jane Doe")).size(), 1); - } - } - } - - @Test - public void testCommitRemove() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - txRepo.remove(where("name").eq("John")); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 0); - assertEquals(repository.find(where("name").eq("John")).size(), 1); - - transaction.commit(); - - assertEquals(repository.find(where("name").eq("John")).size(), 0); - } - } - } - - @Test - public void testRollbackRemove() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - TxData txData1 = new TxData(1L, "John"); - repository.insert(txData1); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - txRepo.remove(where("name").eq("John")); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 0); - assertEquals(repository.find(where("name").eq("John")).size(), 1); - - TxData txData2 = new TxData(2L, "Jane"); - txRepo.insert(txData2); - repository.insert(txData2); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(repository.find(where("name").eq("John")).size(), 1); - assertEquals(repository.find(where("name").eq("Jane")).size(), 1); - } - } - } - - @Test - public void testCommitCreateIndex() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.createIndex("name", indexOptions(IndexType.Fulltext)); - - assertTrue(txRepo.hasIndex("name")); - assertFalse(repository.hasIndex("name")); - - transaction.commit(); - - assertTrue(repository.hasIndex("name")); - } - } - } - - @Test - public void testRollbackCreateIndex() { - TxData txData1 = new TxData(1L, "John"); - TxData txData2 = new TxData(2L, "Jane"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.createIndex("name", indexOptions(IndexType.Fulltext)); - - assertTrue(txRepo.hasIndex("name")); - assertFalse(repository.hasIndex("name")); - - txRepo.insert(txData2); - repository.insert(txData2); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertFalse(repository.hasIndex("name")); - } - } - } - - @Test - public void testCommitClear() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.clear(); - - assertEquals(0, txRepo.size()); - assertEquals(1, repository.size()); - - transaction.commit(); - - assertEquals(0, repository.size()); - } - } - } - - @Test - public void testRollbackClear() { - TxData txData1 = new TxData(1L, "John"); - TxData txData2 = new TxData(2L, "Jane"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.clear(); - - assertEquals(0, txRepo.size()); - assertEquals(1, repository.size()); - - txRepo.insert(txData2); - repository.insert(txData2); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(2, repository.size()); - } - } - } - - @Test - public void testCommitDropIndex() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.dropIndex("name"); - - assertFalse(txRepo.hasIndex("name")); - assertTrue(repository.hasIndex("name")); - - transaction.commit(); - - assertFalse(repository.hasIndex("name")); - } - } - } - - @Test - public void testRollbackDropIndex() { - TxData txData1 = new TxData(1L, "John"); - TxData txData2 = new TxData(2L, "Jane"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.dropIndex("name"); - - assertFalse(txRepo.hasIndex("name")); - assertTrue(repository.hasIndex("name")); - - txRepo.insert(txData2); - repository.insert(txData2); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertTrue(repository.hasIndex("name")); - } - } - } - - @Test - public void testCommitDropAllIndices() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.dropAllIndices(); - - assertFalse(txRepo.hasIndex("name")); - assertTrue(repository.hasIndex("name")); - - transaction.commit(); - - assertFalse(repository.hasIndex("name")); - } - } - } - - @Test - public void testRollbackDropAllIndices() { - TxData txData1 = new TxData(1L, "John"); - TxData txData2 = new TxData(2L, "Jane"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.dropAllIndices(); - - assertFalse(txRepo.hasIndex("name")); - assertTrue(repository.hasIndex("name")); - - txRepo.insert(txData2); - repository.insert(txData2); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertTrue(repository.hasIndex("name")); - } - } - } - - @Test - public void testCommitDropRepository() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.drop(); - - boolean expectedException = false; - try { - assertEquals(0, txRepo.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - assertEquals(1, repository.size()); - - transaction.commit(); - - expectedException = false; - try { - assertEquals(0, repository.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - } - } - } - - @Test - public void testRollbackDropRepository() { - TxData txData1 = new TxData(1L, "John"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.drop(); - - boolean expectedException = false; - try { - assertEquals(0, txRepo.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - assertEquals(1, repository.size()); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(1, repository.size()); - } - } - } - - @Test - public void testCommitSetAttribute() { - ObjectRepository repository = db.getRepository(TxData.class); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - Attributes attributes = new Attributes(); - attributes.setAttributes(Collections.singletonMap("key", "value")); - txRepo.setAttributes(attributes); - - assertNull(repository.getAttributes()); - - transaction.commit(); - - assertEquals("value", repository.getAttributes().get("key")); - } - } - } - - @Test - public void testRollbackSetAttribute() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - Attributes attributes = new Attributes(); - Map map = new HashMap<>(); - map.put("key", "value"); - attributes.setAttributes(map); - txRepo.setAttributes(attributes); - - txRepo.insert(new TxData(1L, "John")); - txRepo.insert(new TxData(2L, "Jane")); - - assertNull(repository.getAttributes()); - - // just to create UniqueConstraintViolation for rollback - repository.insert(new TxData(2L, "Jane")); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 1); - assertNotEquals(repository.find(where("name").eq("John")).size(), 1); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertNull(repository.getAttributes().get("key")); - } - } - } - - @Test - public void testConcurrentInsertAndRemove() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.NonUnique)); - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - final long fi = i; - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - for (long j = 0; j < 10; j++) { - TxData txData = new TxData(j + (fi * 10), faker.name().name()); - txRepo.insert(txData); - } - - txRepo.remove(where("id").eq(2L + (fi * 10))); - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(90, repository.size()); - } - } - - @Test - public void testConcurrentInsert() { - ObjectRepository repository = db.getRepository(TxData.class); - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - final long fi = i; - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - for (long j = 0; j < 10; j++) { - TxData txData = new TxData(j + (fi * 10), faker.name().name()); - txRepo.insert(txData); - } - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(100, repository.size()); - } - } - - @Test - public void testConcurrentUpdate() { - ObjectRepository repository = db.getRepository(TxData.class); - Faker faker = new Faker(); - for (long j = 0; j < 10; j++) { - TxData txData = new TxData(j, faker.name().name()); - repository.insert(txData); - } - - List> futures = new ArrayList<>(); - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - for (int j = 0; j < 10; j++) { - TxData txData = new TxData((long) j, faker.name().name()); - txRepo.update(where("id").eq(j), txData); - } - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(10, repository.size()); - } - } - - @Test - public void testTransactionOnDifferentRepositoriesAndCollections() { - ObjectRepository repo1 = db.getRepository(TxData.class); - ObjectRepository repo2 = db.getRepository(TxData.class, "2"); - ObjectRepository repo3 = db.getRepository(SubEmployee.class); - NitriteCollection col1 = db.getCollection("test1"); - col1.createIndex("id", indexOptions(IndexType.Unique)); - - Faker faker = new Faker(); - - try(Session session = db.createSession()) { - Transaction transaction = session.beginTransaction(); - - ObjectRepository txRepo1 = transaction.getRepository(TxData.class); - ObjectRepository txRepo2 = transaction.getRepository(TxData.class, "2"); - ObjectRepository txRepo3 = transaction.getRepository(SubEmployee.class); - NitriteCollection test1 = transaction.getCollection("test1"); - - for (long i = 0; i < 10; i++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", i); - test1.insert(document); - - TxData txData1 = new TxData(i, faker.name().name()); - txRepo1.insert(txData1); - - TxData txData2 = new TxData(i + 10, faker.name().name()); - txRepo2.insert(txData2); - - SubEmployee employee = new SubEmployee(); - employee.setAddress(faker.address().fullAddress()); - employee.setEmpId(i); - employee.setJoinDate(faker.date().birthday()); - txRepo3.insert(employee); - } - - assertEquals(test1.size(), 10); - assertEquals(txRepo1.size(), 10); - assertEquals(txRepo2.size(), 10); - assertEquals(txRepo3.size(), 10); - - assertEquals(col1.size(), 0); - assertEquals(repo1.size(), 0); - assertEquals(repo2.size(), 0); - assertEquals(repo3.size(), 0); - - transaction.commit(); - - assertEquals(col1.size(), 10); - assertEquals(repo1.size(), 10); - assertEquals(repo2.size(), 10); - assertEquals(repo3.size(), 10); - } - - Transaction transaction = null; - try (Session session = db.createSession()) { - transaction = session.beginTransaction(); - - ObjectRepository txRepo1 = transaction.getRepository(TxData.class); - ObjectRepository txRepo2 = transaction.getRepository(TxData.class, "2"); - ObjectRepository txRepo3 = transaction.getRepository(SubEmployee.class); - NitriteCollection test1 = transaction.getCollection("test1"); - - for (long i = 0; i < 10; i++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 10); - test1.insert(document); - - TxData txData1 = new TxData(i + 10, faker.name().name()); - txRepo1.insert(txData1); - - TxData txData2 = new TxData(i + 20, faker.name().name()); - txRepo2.insert(txData2); - - SubEmployee employee = new SubEmployee(); - employee.setAddress(faker.address().fullAddress()); - employee.setEmpId(i + 10); - employee.setJoinDate(faker.date().birthday()); - txRepo3.insert(employee); - } - - assertEquals(test1.size(), 20); - assertEquals(txRepo1.size(), 20); - assertEquals(txRepo2.size(), 20); - assertEquals(txRepo3.size(), 20); - - assertEquals(col1.size(), 10); - assertEquals(repo1.size(), 10); - assertEquals(repo2.size(), 10); - assertEquals(repo3.size(), 10); - - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", 12L); - col1.insert(document); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - - assertEquals(col1.size(), 11); // last doc added - assertEquals(repo1.size(), 10); - assertEquals(repo2.size(), 10); - assertEquals(repo3.size(), 10); - } - } - - @Test(expected = TransactionException.class) - public void testFailureOnClosedTransaction() { - try(Session session = db.createSession()) { - Transaction transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.insert(new TxData(1L, "John")); - transaction.commit(); - - txRepo.insert(new TxData(2L, "Jane")); - fail(); - } - } -} diff --git a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/transaction/TxData.java b/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/transaction/TxData.java deleted file mode 100644 index f31a212e2..000000000 --- a/nitrite-mapdb-adapter/src/test/java/org/dizitart/no2/mapdb/transaction/TxData.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapdb.transaction; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -class TxData implements Mappable { - @Id - private Long id; - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("id", id) - .put("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Long.class); - name = document.get("name", String.class); - } -} diff --git a/nitrite-mapdb-adapter/src/test/resources/english.stop b/nitrite-mapdb-adapter/src/test/resources/english.stop deleted file mode 100644 index 70572ebaa..000000000 --- a/nitrite-mapdb-adapter/src/test/resources/english.stop +++ /dev/null @@ -1,571 +0,0 @@ -a -a's -able -about -above -according -accordingly -across -actually -after -afterwards -again -against -ain't -all -allow -allows -almost -alone -along -already -also -although -always -am -among -amongst -an -and -another -any -anybody -anyhow -anyone -anything -anyway -anyways -anywhere -apart -appear -appreciate -appropriate -are -aren't -around -as -aside -ask -asking -associated -at -available -away -awfully -b -be -became -because -become -becomes -becoming -been -before -beforehand -behind -being -believe -below -beside -besides -best -better -between -beyond -both -brief -but -by -c -c'mon -c's -came -can -can't -cannot -cant -cause -causes -certain -certainly -changes -clearly -co -com -come -comes -concerning -consequently -consider -considering -contain -containing -contains -corresponding -could -couldn't -course -currently -d -definitely -described -despite -did -didn't -different -do -does -doesn't -doing -don't -done -down -downwards -during -e -each -edu -eg -eight -either -else -elsewhere -enough -entirely -especially -et -etc -even -ever -every -everybody -everyone -everything -everywhere -ex -exactly -example -except -f -far -few -fifth -first -five -followed -following -follows -for -former -formerly -forth -four -from -further -furthermore -g -get -gets -getting -given -gives -go -goes -going -gone -got -gotten -greetings -h -had -hadn't -happens -hardly -has -hasn't -have -haven't -having -he -he's -hello -help -hence -her -here -here's -hereafter -hereby -herein -hereupon -hers -herself -hi -him -himself -his -hither -hopefully -how -howbeit -however -i -i'd -i'll -i'm -i've -ie -if -ignored -immediate -in -inasmuch -inc -indeed -indicate -indicated -indicates -inner -insofar -instead -into -inward -is -isn't -it -it'd -it'll -it's -its -itself -j -just -k -keep -keeps -kept -know -knows -known -l -last -lately -later -latter -latterly -least -less -lest -let -let's -like -liked -likely -little -look -looking -looks -ltd -m -mainly -many -may -maybe -me -mean -meanwhile -merely -might -more -moreover -most -mostly -much -must -my -myself -n -name -namely -nd -near -nearly -necessary -need -needs -neither -never -nevertheless -new -next -nine -no -nobody -non -none -noone -nor -normally -not -nothing -novel -now -nowhere -o -obviously -of -off -often -oh -ok -okay -old -on -once -one -ones -only -onto -or -other -others -otherwise -ought -our -ours -ourselves -out -outside -over -overall -own -p -particular -particularly -per -perhaps -placed -please -plus -possible -presumably -probably -provides -q -que -quite -qv -r -rather -rd -re -really -reasonably -regarding -regardless -regards -relatively -respectively -right -s -said -same -saw -say -saying -says -second -secondly -see -seeing -seem -seemed -seeming -seems -seen -self -selves -sensible -sent -serious -seriously -seven -several -shall -she -should -shouldn't -since -six -so -some -somebody -somehow -someone -something -sometime -sometimes -somewhat -somewhere -soon -sorry -specified -specify -specifying -still -sub -such -sup -sure -t -t's -take -taken -tell -tends -th -than -thank -thanks -thanx -that -that's -thats -the -their -theirs -them -themselves -then -thence -there -there's -thereafter -thereby -therefore -therein -theres -thereupon -these -they -they'd -they'll -they're -they've -think -third -this -thorough -thoroughly -those -though -three -through -throughout -thru -thus -to -together -too -took -toward -towards -tried -tries -truly -try -trying -twice -two -u -un -under -unfortunately -unless -unlikely -until -unto -up -upon -us -use -used -useful -uses -using -usually -uucp -v -value -various -very -via -viz -vs -w -want -wants -was -wasn't -way -we -we'd -we'll -we're -we've -welcome -well -went -were -weren't -what -what's -whatever -when -whence -whenever -where -where's -whereafter -whereas -whereby -wherein -whereupon -wherever -whether -which -while -whither -who -who's -whoever -whole -whom -whose -why -will -willing -wish -with -within -without -won't -wonder -would -would -wouldn't -x -y -yes -yet -you -you'd -you'll -you're -you've -your -yours -yourself -yourselves -z -zero \ No newline at end of file diff --git a/nitrite-mapdb-adapter/src/test/resources/log4j2.xml b/nitrite-mapdb-adapter/src/test/resources/log4j2.xml deleted file mode 100644 index ece1f583c..000000000 --- a/nitrite-mapdb-adapter/src/test/resources/log4j2.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/nitrite-mapdb-adapter/src/test/resources/test.text b/nitrite-mapdb-adapter/src/test/resources/test.text deleted file mode 100644 index c940fb50c..000000000 --- a/nitrite-mapdb-adapter/src/test/resources/test.text +++ /dev/null @@ -1,50 +0,0 @@ -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean massa nulla, elementum vitae velit nec, suscipit porttitor urna. Integer volutpat nibh et nisi congue ullamcorper. Cras laoreet consectetur massa a luctus. Etiam non sapien vitae enim semper elementum. Donec ullamcorper nibh quis magna vestibulum, eget faucibus sem posuere. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Ut sed nulla id risus ultricies facilisis. Curabitur scelerisque eros metus, in ultrices libero efficitur sit amet. Vivamus aliquet nec sapien sed vehicula. Praesent a mauris eget tortor consectetur euismod. Suspendisse tempus felis et ante dictum, nec eleifend tellus finibus. -Vivamus felis turpis, pretium id gravida ut, pharetra et massa. Duis lobortis velit in nibh tristique, sit amet tristique neque eleifend. Quisque et faucibus magna. Donec in enim odio. Vestibulum fringilla odio quis libero convallis, sed imperdiet ante scelerisque. Suspendisse rutrum, turpis eget mollis ultricies, purus ante pellentesque arcu, ut gravida libero elit eget odio. Nam quis congue purus. Sed commodo enim lacus, eu tristique nisi pretium id. Nulla diam odio, cursus a eleifend eu, tristique tempus dui. -Suspendisse dictum mollis justo. Aliquam tempus consectetur elit, in euismod erat tempor non. Nullam lacinia eget sapien quis luctus. Praesent odio nisl, dapibus sit amet pharetra ut, consequat et neque. Ut consequat, ligula at lacinia ultrices, erat nisl vehicula urna, at ullamcorper magna urna ut erat. Integer at orci fringilla, congue nibh et, lacinia lorem. Sed aliquet quis felis nec fringilla. Integer egestas vitae neque in consequat. In laoreet nisi risus, a pharetra mi placerat a. Etiam ultricies arcu non est volutpat fringilla. Ut et molestie augue, ac consequat urna. Nulla et egestas mi. Sed tempor tortor et velit lacinia volutpat. Etiam volutpat porta interdum. Aliquam vitae rutrum sem. -Phasellus venenatis nibh mauris, id lobortis lorem dictum quis. Cras at sagittis felis. Proin viverra neque et metus rhoncus suscipit. Nam aliquet aliquet est, eget convallis turpis hendrerit sit amet. Nam eget commodo justo. Morbi pharetra commodo sapien vitae luctus. Integer eu eleifend massa. Integer consectetur sapien nec ligula pellentesque, sit amet tempus lacus venenatis. Aenean efficitur risus sed ligula dapibus pellentesque. Sed consectetur est eget egestas ornare. -Integer sit amet iaculis orci. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec non dignissim nibh, sit amet ornare ipsum. Proin quis felis ut orci condimentum mattis a non urna. Aenean a metus nec lacus fringilla scelerisque sit amet id nisi. Nulla et velit in libero laoreet mollis. Nam malesuada leo non enim hendrerit facilisis a quis enim. -Nullam in diam ut ex mattis aliquet sed et ipsum. Morbi ut nunc et ex mollis convallis. Donec dui velit, iaculis at sapien ullamcorper, dictum maximus nibh. Maecenas porttitor arcu quis ex molestie elementum. Donec scelerisque ut erat at finibus. Nunc nec tempor mauris, sed posuere magna. In hac habitasse platea dictumst. Phasellus elit nisl, pellentesque vestibulum arcu quis, accumsan cursus nisi. Nunc eget orci non felis pretium vestibulum nec in mi. Nulla tincidunt, tortor id bibendum scelerisque, nibh libero lacinia felis, at pretium arcu lectus eu justo. Aenean ac elit id leo finibus vehicula. -Donec sed orci lobortis, posuere purus nec, molestie odio. Mauris elementum libero vel nibh ultrices vehicula. Quisque dignissim ipsum libero, eu elementum quam dignissim a. Mauris magna felis, tincidunt eu dolor vel, sollicitudin porta mi. Integer tempor volutpat leo. Nunc a neque lectus. Nullam pretium tempus congue. -Sed vehicula ipsum ipsum, et maximus augue gravida ut. Nunc augue lorem, volutpat ac volutpat nec, commodo ut ex. Duis dignissim est enim, non dapibus urna pharetra a. Aliquam vitae viverra nibh, ut ullamcorper nulla. Pellentesque ultricies aliquet magna, eget fermentum turpis. Etiam ut urna elementum, laoreet est ut, commodo quam. In quis libero vitae lacus scelerisque dignissim. Phasellus libero ligula, porttitor ac enim sed, ultrices accumsan erat. Quisque cursus tortor sit amet tellus laoreet, eu finibus velit laoreet. Duis luctus massa non nulla luctus, at imperdiet lacus condimentum. Ut nulla metus, elementum sed porta id, fringilla non enim. Fusce id rutrum ipsum. Etiam rhoncus finibus faucibus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. -Etiam placerat aliquet nunc, id facilisis metus auctor at. Ut mi lacus, pharetra in egestas in, accumsan nec urna. Donec placerat erat quis enim vehicula, eget sollicitudin elit auctor. Curabitur ac auctor mauris. Nulla facilisi. Nam suscipit commodo mi, ut consequat neque finibus et. Fusce vestibulum porttitor odio, at tincidunt urna consectetur eu. Nullam lobortis risus sed convallis commodo. Cras non nibh vehicula, venenatis eros non, ultricies neque. Pellentesque enim nisl, elementum et libero id, laoreet dapibus odio. Aenean quis erat suscipit, mattis lectus quis, consectetur nibh. Vivamus vel sem egestas, ultricies mauris at, bibendum velit. Phasellus cursus elit erat, ut molestie risus condimentum vitae. Nam sapien mauris, ullamcorper sit amet dui id, accumsan lobortis dolor. Curabitur ultrices metus felis, ac sollicitudin eros vulputate at. Nunc eget tristique eros. -Vestibulum in lobortis nulla. Morbi mattis turpis ut tellus rutrum, at consectetur lacus mollis. Etiam maximus lectus ante, scelerisque aliquet turpis pharetra et. Fusce vulputate efficitur enim, at varius augue sagittis nec. Aenean volutpat volutpat metus, ut faucibus ex posuere dictum. Vivamus est enim, volutpat aliquam mi vel, dictum lobortis leo. Cras luctus fermentum tellus, sodales pellentesque lectus rutrum id. Sed in condimentum leo. Etiam ultricies porttitor ligula, et sodales purus imperdiet ac. Praesent non semper mi. Nullam bibendum auctor mi sit amet malesuada. Maecenas luctus accumsan ante feugiat egestas. Mauris tellus felis, venenatis sit amet risus nec, auctor auctor libero. Suspendisse purus risus, suscipit at lectus ut, maximus convallis nunc. Nulla facilisi. -Quisque commodo diam ut dui tristique luctus. Nam dignissim semper sollicitudin. Aenean condimentum orci ut augue suscipit, vitae ullamcorper urna ultrices. Nunc ac arcu eu massa placerat maximus. Cras ultrices elit id ipsum finibus, sit amet lacinia dui dignissim. Nulla suscipit suscipit libero non posuere. Aenean lobortis cursus metus, eu dignissim ligula pellentesque a. Donec viverra varius luctus. Mauris quis neque erat. Quisque pellentesque volutpat felis ultricies feugiat. -Fusce eu ante bibendum, tincidunt mauris bibendum, vulputate diam. Integer sit amet massa maximus, finibus ipsum in, scelerisque nunc. Quisque sodales neque quis tristique porttitor. Suspendisse molestie sed arcu nec commodo. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec gravida nunc at fringilla accumsan. Praesent id elit sem. Sed sagittis sed nunc sit amet volutpat. Suspendisse potenti. Etiam malesuada neque enim, a consectetur justo ultricies ac. -Aenean vel enim a diam aliquet tempor. Phasellus et blandit dui. Nulla facilisi. Vestibulum rhoncus dolor at risus vehicula, ut tincidunt arcu sodales. Duis at massa ut leo suscipit mollis hendrerit nec justo. Nullam ex erat, accumsan eu odio sit amet, ullamcorper hendrerit ligula. Nullam scelerisque ut turpis vitae imperdiet. Pellentesque fermentum urna id ex mollis, vel mattis leo interdum. -Aenean nec est ac est varius elementum. Vestibulum vulputate accumsan pellentesque. Sed pellentesque mi nec ipsum tincidunt, fringilla faucibus urna semper. Pellentesque quis consequat nisl. Sed viverra nulla sagittis ante blandit, nec vulputate purus dapibus. Nullam molestie nisi diam, vitae elementum massa pellentesque eu. Vestibulum lacinia tortor in nisi auctor, ut pharetra dui interdum. Mauris ac ante elit. -Praesent pharetra egestas sapien ut convallis. Pellentesque gravida maximus maximus. Aliquam tristique venenatis arcu, ut bibendum augue lacinia vel. Nulla vulputate sit amet nibh non vestibulum. Pellentesque et imperdiet ex, vel cursus dui. Integer facilisis, est et tincidunt cursus, ligula arcu faucibus tortor, id commodo orci orci in neque. Nam lacinia lectus tempus, finibus libero pretium, tempor nulla. Lorem ipsum dolor sit amet, consectetur adipiscing elit. -Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed massa ipsum, rhoncus pellentesque dui vestibulum, accumsan lacinia risus. Suspendisse ullamcorper enim vel sem blandit aliquet. Pellentesque bibendum erat eget quam pretium, sit amet cursus velit volutpat. Sed eget nunc at odio tristique venenatis. Mauris id sagittis quam, non aliquam magna. Curabitur sit amet neque a odio blandit consequat eu at est. Fusce in bibendum ipsum, quis fringilla justo. Nunc ut arcu non dui pretium vestibulum nec eu ipsum. Morbi ac dictum nulla. Vivamus vitae velit dolor. Duis quis aliquet felis. Praesent eu nulla vitae ex mattis imperdiet. -Aliquam finibus mauris arcu, non pellentesque diam interdum id. Praesent ornare lectus augue, eget lacinia odio venenatis a. Proin vulputate, nisl at feugiat euismod, massa arcu feugiat massa, a vehicula lorem nisi at diam. Aenean mattis, tellus sed hendrerit efficitur, purus purus consectetur nulla, a suscipit ipsum tortor vel magna. Nam sed posuere sem. Aliquam tincidunt in tortor ac cursus. Ut pellentesque urna in purus scelerisque, et imperdiet orci mollis. Fusce ultrices massa nisl, nec facilisis purus scelerisque ut. Pellentesque malesuada scelerisque diam, et dignissim orci ultricies vitae. Proin molestie ac augue at aliquet. Pellentesque fermentum dapibus purus ac porta. Nunc eu augue dui. Proin lacinia, enim at pretium vulputate, arcu arcu egestas ipsum, vel vehicula metus neque sed ex. Suspendisse vitae odio eu sapien pellentesque fermentum in nec leo. -Maecenas accumsan urna eros, id consequat felis maximus ac. Quisque id dictum sapien, et maximus justo. Sed blandit sit amet arcu ac vulputate. Sed bibendum maximus volutpat. Mauris dignissim purus vel leo ultrices aliquet. Aenean vitae sem rhoncus, vehicula sem quis, cursus metus. Duis hendrerit metus a fringilla sollicitudin. Morbi pellentesque velit eget posuere rhoncus. -Maecenas ullamcorper congue egestas. Aliquam maximus ullamcorper velit, vel ultrices ex pulvinar a. Sed convallis, metus eu facilisis lacinia, ex ante sollicitudin ipsum, vitae malesuada nibh nulla quis nulla. Aenean molestie, nulla commodo mattis viverra, purus mi ultrices ligula, ac accumsan libero velit sed est. Praesent cursus tincidunt ipsum nec sodales. Sed aliquet risus et odio lacinia, ac molestie libero posuere. Donec ultrices quam sapien, vel maximus eros malesuada eu. Integer tempor scelerisque laoreet. Vestibulum placerat rhoncus consequat. Nullam hendrerit, eros faucibus dictum faucibus, urna odio lobortis orci, ac suscipit ipsum lorem condimentum odio. Sed sollicitudin at odio sed viverra. Nulla aliquet facilisis ultrices. -Etiam vitae tempor tellus. Suspendisse potenti. Mauris sit amet odio diam. Vivamus at dignissim dui. Cras at nisl ut lorem condimentum vehicula. Cras vel nunc lectus. Morbi consequat dictum aliquet. Sed fermentum elementum ipsum, tempor fringilla libero varius et. -Mauris sed dictum purus, et ullamcorper tortor. Duis quis gravida urna. Integer pellentesque, ipsum at laoreet commodo, arcu dui semper lectus, sit amet consectetur diam nibh ut justo. Nam condimentum tincidunt arcu nec congue. Sed vulputate ligula at quam ultricies, et pretium justo consequat. Aenean nunc nisi, vehicula sed velit ut, pharetra egestas orci. Mauris pharetra erat tincidunt, gravida ipsum vitae, fermentum purus. Pellentesque sodales libero non purus ornare fermentum. Aliquam laoreet dignissim sem, et placerat turpis tincidunt non. -Cras bibendum ornare consequat. Donec non enim blandit, varius lorem sit amet, aliquam nibh. Morbi orci libero, egestas vitae arcu a, mollis interdum ante. Nullam vulputate risus enim, sit amet bibendum risus semper ut. Donec at orci sit amet ante hendrerit iaculis a non massa. Vestibulum nisi velit, dictum quis ullamcorper in, rhoncus sed ipsum. Curabitur sollicitudin diam dictum volutpat suscipit. Curabitur a elit et orci pellentesque venenatis ut rhoncus tellus. Proin nec metus non leo pharetra aliquet. Sed dolor augue, vehicula in odio vitae, cursus tincidunt eros. Praesent tempus luctus metus ac maximus. Phasellus non nibh quis eros rhoncus eleifend quis vitae nisi. -In ante enim, convallis in mollis nec, rutrum a nulla. Sed a urna ac nibh pharetra volutpat sit amet vel tortor. Quisque sodales tincidunt felis, et sollicitudin ligula venenatis vel. Pellentesque non justo eu diam sodales venenatis sed nec lacus. Nulla dignissim, sapien non pharetra scelerisque, risus massa dictum purus, congue convallis ante diam nec erat. Maecenas malesuada efficitur neque, a condimentum erat finibus vitae. Mauris quis dolor cursus nisi eleifend convallis sed id diam. Sed non pellentesque nisi. Praesent ut velit et tellus eleifend lacinia. Sed suscipit rutrum viverra. Pellentesque eget malesuada diam. Ut sed leo egestas, gravida odio aliquam, sodales nulla. In in lobortis nunc. Mauris et ex volutpat, elementum risus a, maximus magna. -Donec at odio sit amet nulla maximus semper at in elit. Vestibulum fringilla a tortor ut tristique. Proin a tristique mi. Cras libero ipsum, blandit ut volutpat non, convallis ac erat. Vivamus condimentum nunc dignissim, vestibulum tellus ut, tempus ante. Suspendisse fringilla nisi id arcu blandit pellentesque. Etiam vel elit velit. Donec ac sem consectetur, pharetra nisi a, facilisis turpis. Integer nec aliquam risus. Nullam posuere ligula eu purus rhoncus, nec fringilla nulla blandit. -Fusce condimentum sapien in elit dictum, ullamcorper vulputate ligula lacinia. Donec placerat elit dignissim mauris pellentesque malesuada. Maecenas semper lectus quis orci varius porta. Cras nec magna vitae ligula gravida bibendum. Pellentesque gravida purus sapien, eu egestas orci cursus sodales. Fusce varius ultrices enim quis faucibus. Aenean vel lobortis ex. Integer scelerisque nulla vel ligula pretium eleifend. Morbi lacus ligula, semper nec aliquet a, pulvinar nec ligula. Duis est orci, varius at ultricies ut, molestie id arcu. Nulla molestie lectus pharetra tortor cursus, eget gravida justo tempor. Fusce non ornare ante. In eu tortor venenatis, aliquet augue a, euismod purus. Duis et nibh venenatis, gravida nisi ut, sodales mi. Ut at ligula pretium, laoreet velit rutrum, sodales neque. Nulla quam nulla, mattis quis erat in, bibendum laoreet sem. -Donec posuere diam et est fringilla, sit amet malesuada lectus auctor. Nulla diam ante, tincidunt eu elementum in, congue vitae ante. Curabitur vulputate, nunc at posuere consectetur, nunc sem sagittis felis, non iaculis elit arcu eu metus. Pellentesque a eros dui. Phasellus commodo risus ante, at placerat augue ultricies a. Mauris in elementum velit. Curabitur quis odio vel tellus lacinia porttitor. Mauris nec mollis est, eget efficitur tellus. -In porttitor vel lectus vel finibus. Nunc quis quam ac nunc fringilla tempor. Pellentesque vel malesuada nunc. Suspendisse interdum pretium turpis, eget pretium tellus facilisis at. Etiam id ipsum eu velit elementum vehicula. Mauris vulputate lacus ac elit semper, a sodales metus varius. In semper ligula non erat vulputate, nec sollicitudin lectus gravida. Suspendisse porttitor sapien quis consectetur euismod. Maecenas consectetur scelerisque augue, eu iaculis dolor vulputate eget. In lobortis tristique mauris eu elementum. Proin lacus libero, suscipit id eleifend tincidunt, tincidunt vel felis. Aenean vulputate leo nec odio vehicula, venenatis tempus purus rutrum. -Curabitur non mauris vitae velit tempor dictum. Morbi id congue nunc. Aliquam imperdiet nec eros vitae pulvinar. Donec ut lobortis mauris. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vivamus pellentesque ante sem, vitae feugiat ante lobortis ut. Aliquam felis est, accumsan eget lacus at, gravida gravida ipsum. Etiam congue est justo, sed elementum erat aliquet quis. Aenean porttitor massa pellentesque, efficitur lacus non, scelerisque justo. Integer commodo turpis nibh, eget tincidunt mauris consequat id. Sed convallis egestas rhoncus. In faucibus mi sit amet dolor tempor, non ullamcorper erat mollis. -Quisque tincidunt feugiat volutpat. Nunc consectetur sapien finibus ipsum tincidunt, sit amet facilisis justo suscipit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque scelerisque massa eros, eget tempor lorem rutrum sit amet. Mauris faucibus libero at est sodales elementum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum dapibus ipsum ac quam placerat, eget lacinia lorem lobortis. Pellentesque eget velit nunc. Integer elementum justo in erat lobortis scelerisque. Sed ultrices dapibus quam quis ullamcorper. Duis auctor commodo placerat. Vivamus sed gravida turpis. Cras et nisl dignissim, pellentesque quam sed, eleifend nibh. Pellentesque et metus vel ipsum interdum bibendum. -Nam porttitor tristique metus eget elementum. Nullam eget risus commodo, malesuada dolor sit amet, tempus leo. Etiam eu iaculis neque, in tristique enim. Sed fringilla convallis leo id eleifend. Donec id purus suscipit, iaculis elit a, luctus felis. Praesent laoreet vulputate mi, eget cursus odio venenatis vitae. Curabitur egestas sem enim, non luctus erat tincidunt consectetur. Sed non viverra tellus. -Donec sodales ex eu neque condimentum feugiat. Integer elementum efficitur ligula quis aliquam. Quisque gravida tincidunt mauris. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Quisque ut vehicula tellus. Maecenas ultricies est ac quam aliquam, eget tincidunt eros bibendum. Curabitur a viverra risus, ut dignissim lacus. Praesent pharetra vulputate porttitor. Suspendisse cursus egestas nisl, in mattis risus imperdiet non. Ut tempus tortor malesuada dapibus tristique. Sed blandit ligula non lacus tincidunt pellentesque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Fusce semper mattis ante, in efficitur ligula egestas sit amet. -Nullam eu dapibus nisi, nec fermentum enim. Duis orci odio, lobortis nec ullamcorper a, faucibus fringilla est. Aenean convallis, lorem non euismod venenatis, sapien ipsum pulvinar ipsum, non auctor arcu massa in nisi. Maecenas tincidunt sapien ante, in consequat dui accumsan eget. Phasellus id tellus ac libero iaculis fermentum. Vestibulum sagittis sapien quis porttitor facilisis. Cras euismod sollicitudin nisi, et pretium sapien hendrerit a. Ut auctor vitae neque id pellentesque. Donec at dui blandit, ultricies orci et, aliquet mauris. Praesent porttitor massa vel diam ultrices, ac convallis tellus tincidunt. Duis molestie condimentum nisl non venenatis. Pellentesque scelerisque odio ut lobortis porttitor. Donec congue interdum dolor, non sagittis tellus mattis vel. Fusce commodo augue fringilla semper gravida. -Sed placerat erat nulla, at commodo enim dapibus id. Integer augue dui, aliquet a eros at, euismod luctus erat. Donec vitae tempus enim. In luctus posuere sollicitudin. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Phasellus ultrices a felis tincidunt condimentum. Integer nulla augue, pellentesque eu facilisis id, congue dignissim ligula. Phasellus vestibulum blandit vulputate. Morbi a tempus eros. Maecenas ac metus vehicula massa egestas rhoncus. Nam accumsan porttitor rutrum. Morbi sollicitudin eros vestibulum tortor finibus, nec porta orci eleifend. Curabitur id suscipit quam. -Donec vehicula metus massa, accumsan vulputate dolor bibendum vel. Curabitur tincidunt magna sit amet massa commodo, quis porttitor libero sollicitudin. Aenean sollicitudin vehicula dignissim. Duis rhoncus varius leo, vitae eleifend eros tristique quis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Quisque fermentum nulla purus, nec aliquam nunc ultrices ut. Praesent vestibulum risus eu dolor ultricies eleifend. Nulla vitae hendrerit lorem, a pellentesque eros. Praesent pellentesque sit amet arcu ac hendrerit. -Ut scelerisque, velit eu rhoncus eleifend, dolor dui ultricies dolor, id fermentum lectus nunc nec sem. Donec eget nisi eget augue consequat pretium. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sollicitudin eget magna sed varius. Nam ultricies, eros non dapibus varius, eros elit finibus metus, quis semper lacus lectus in turpis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Praesent ornare, sapien vel gravida semper, risus risus luctus ligula, in vestibulum nibh arcu ac tortor. In cursus tempus justo eget mollis. Phasellus eget mauris hendrerit, venenatis dolor quis, euismod neque. Suspendisse potenti. -Suspendisse lorem lectus, accumsan eget ipsum ac, commodo luctus velit. Vivamus non ligula enim. In hendrerit turpis ut mauris commodo sagittis. Sed dapibus dolor vel turpis malesuada, id tincidunt ipsum convallis. Nulla in convallis enim, at dignissim mi. Etiam at mauris eget eros viverra malesuada. Etiam malesuada ligula eu libero condimentum pretium. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed eget quam non purus malesuada tristique. -Aenean at arcu felis. Donec consectetur ante a tellus pellentesque sollicitudin. Duis ut arcu sapien. Aenean quis lacus a turpis porttitor egestas ut nec nisi. Aenean viverra nec nunc quis lacinia. Nulla dapibus eros ac placerat blandit. Morbi tincidunt porttitor sapien, eu aliquet ipsum ullamcorper at. Phasellus eleifend lacus et mauris mollis gravida. Nullam vitae luctus mauris. Integer malesuada nec ligula non gravida. Nullam at facilisis neque. Vestibulum ac est a libero sagittis tempor a et urna. Suspendisse ac sollicitudin leo, in aliquet augue. Curabitur non vulputate mi. Ut eget euismod ex, ut placerat leo. Praesent suscipit lectus magna, ac bibendum risus dapibus id. -Cras consequat vel nunc id porttitor. Suspendisse tristique nunc leo, quis fermentum diam ultrices ac. Donec scelerisque mollis porttitor. Maecenas interdum dui orci, ut volutpat purus iaculis ac. Proin sed odio est. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vestibulum malesuada turpis nunc, nec tincidunt risus ultricies eu. In pellentesque a leo quis aliquam. Suspendisse potenti. Cras volutpat nibh arcu, sit amet molestie purus rhoncus et. -Phasellus mi neque, placerat sed justo laoreet, aliquet sodales sem. Mauris vulputate aliquam sem, ac consectetur dolor iaculis eget. Nunc lobortis sapien lectus, ac consectetur nisi porta ac. In in sem nec massa consequat viverra nec aliquam urna. Proin maximus posuere tellus quis imperdiet. Suspendisse lobortis viverra aliquet. Duis laoreet, sem at ullamcorper consequat, eros orci maximus urna, non laoreet sapien orci ac ante. Quisque vulputate, magna ac venenatis tincidunt, nunc nibh convallis elit, sit amet mattis quam ipsum condimentum sem. Nunc maximus, nibh in lobortis dapibus, est erat lobortis tortor, eu euismod mi leo eu tellus. Praesent sit amet orci at quam porttitor cursus nec vel mauris. Nullam at sagittis tortor. Vivamus fermentum, quam nec egestas lobortis, velit velit molestie quam, in finibus libero mauris a lacus. -Sed nec dolor a lorem semper rutrum nec sit amet est. Vestibulum blandit bibendum nibh at commodo. Aenean sit amet purus dolor. Curabitur consequat volutpat aliquam. Nullam erat lorem, condimentum quis ultrices at, imperdiet at est. Nullam placerat mi sed facilisis rutrum. Proin metus felis, vulputate lacinia urna sit amet, rutrum fringilla felis. Donec quam lectus, porta sed elit et, dignissim luctus libero. -Suspendisse a augue ante. Phasellus hendrerit elit ut maximus consectetur. Aliquam id nisl ac lectus sodales rutrum quis vehicula purus. Vivamus sollicitudin turpis ac felis ullamcorper, id dictum ante iaculis. Fusce a libero est. In bibendum varius enim, gravida ultricies leo placerat et. Nunc ante erat, hendrerit sed sapien ac, molestie semper libero. Sed sagittis, quam non congue imperdiet, tellus leo ullamcorper metus, eget vestibulum tortor dui at dolor. Mauris est sem, tincidunt vel luctus non, tincidunt eu ipsum. Nullam a feugiat dui. Nunc vel velit vel ipsum sollicitudin dictum. Ut cursus imperdiet nibh, et aliquam ligula lacinia ac. -Cras erat felis, commodo ut posuere id, vehicula id neque. Vestibulum urna dolor, gravida vestibulum libero sed, pretium molestie mauris. Nullam in efficitur ipsum. Donec et ipsum finibus, bibendum diam vel, placerat est. Donec vitae gravida felis. Etiam augue justo, finibus id eros nec, consectetur lobortis risus. Aenean varius accumsan quam, ac pulvinar nunc pretium at. Mauris vitae risus maximus, eleifend leo ac, maximus nunc. Cras nibh ante, rhoncus eu eleifend eget, accumsan eget ex. -Vivamus tincidunt fermentum aliquet. Etiam et venenatis diam. Sed scelerisque convallis eros non pulvinar. Ut dignissim justo eros, id rhoncus magna mollis quis. Nullam lobortis odio at placerat feugiat. Morbi feugiat est eu mauris pellentesque efficitur. Praesent posuere arcu urna, eu cursus leo fermentum sit amet. Curabitur sit amet aliquam odio. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nunc malesuada nulla est, et varius nulla condimentum sed. Sed sit amet eros felis. Nullam vitae pretium lectus. -Etiam at massa vel urna varius accumsan. Proin non porttitor purus, nec facilisis libero. Quisque tristique, mi ac tristique vulputate, ipsum nibh porta urna, et tempus ex orci eu libero. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin non pellentesque elit, at vehicula justo. Ut facilisis mi sit amet est faucibus, id lobortis est varius. Nulla placerat justo lorem, quis condimentum nulla dapibus quis. Curabitur blandit non lorem at ultrices. Duis nunc mauris, cursus porttitor mauris mattis, consequat luctus neque. -Duis congue non quam eget dignissim. Etiam molestie metus et arcu sollicitudin cursus. Suspendisse cursus luctus rhoncus. Proin lorem metus, bibendum pharetra auctor vitae, malesuada eget risus. Aenean ac libero quis metus lacinia dignissim nec vitae tellus. Nulla consectetur semper ipsum, sed imperdiet elit lobortis sit amet. Vivamus iaculis arcu ut mattis iaculis. In metus tortor, euismod sit amet ligula eget, tincidunt euismod dolor. Aliquam eget elit at est faucibus aliquet sit amet quis leo. -Praesent lectus dolor, tincidunt et urna eget, consectetur volutpat libero. Quisque placerat vel sem ac accumsan. Nulla facilisi. Praesent facilisis condimentum quam. Vivamus malesuada nibh ut dignissim commodo. Morbi a egestas leo. Sed viverra, purus eu mattis varius, nibh nunc convallis est, et tristique nulla eros ut augue. Curabitur a dui tortor. Pellentesque viverra nisi ut risus laoreet vehicula. -Suspendisse potenti. Quisque et condimentum tellus. Vestibulum mollis sollicitudin risus, ac suscipit ex interdum ac. Vivamus mattis velit non lectus consectetur aliquam. Maecenas commodo iaculis eros ac suscipit. Quisque tempor libero in ultricies luctus. Phasellus dictum, orci in suscipit fringilla, est dui imperdiet purus, vitae tempor tellus odio et est. Vestibulum iaculis id felis in facilisis. Morbi luctus tortor sit amet dui varius iaculis. Sed gravida ipsum lectus, id tincidunt dui dapibus eget. Proin at vestibulum libero, nec ornare sapien. Quisque odio mi, maximus in pretium et, hendrerit at odio. -Nunc ullamcorper mattis laoreet. In dolor justo, imperdiet eget libero id, imperdiet laoreet erat. Donec molestie dictum leo, nec luctus ipsum viverra nec. Maecenas scelerisque metus sed vulputate ullamcorper. Maecenas varius eget felis vel porttitor. Sed sem diam, pellentesque vitae egestas ut, varius at urna. Donec eu metus commodo augue porta eleifend. Maecenas id porta erat. Aenean sed nunc orci. Ut nec tristique ipsum, ut egestas purus. Nullam egestas dictum tristique. Sed lacinia mauris quis cursus tristique. Quisque ac urna id diam elementum vulputate eu eu purus. -Aliquam sit amet purus bibendum, placerat massa quis, malesuada nisl. Nullam orci justo, egestas eget neque maximus, cursus porttitor velit. Donec vel sodales risus. Curabitur lorem dui, finibus id est a, hendrerit luctus velit. Praesent aliquet molestie felis, nec dictum leo tincidunt vel. Cras rutrum tempus egestas. Sed in ex interdum, lobortis nunc a, pharetra diam. Ut sed risus scelerisque purus rutrum rhoncus ut eget urna. Praesent mollis arcu vel auctor luctus. Nullam risus magna, iaculis non condimentum id, maximus sed diam. Integer porttitor ornare metus sed mattis. Nulla facilisi. Proin facilisis vestibulum dolor, sed hendrerit metus convallis a. Cras rutrum est eget mauris laoreet, nec blandit sapien euismod. -Nulla egestas auctor arcu in porttitor. Integer tincidunt ex non laoreet tincidunt. Suspendisse vitae urna ut nibh auctor viverra nec in lacus. In finibus sagittis velit, non rhoncus sapien tristique non. Suspendisse eu urna cursus, varius turpis vel, semper est. Donec orci augue, mollis sed auctor in, eleifend vitae justo. Cras commodo orci interdum turpis suscipit laoreet. Quisque venenatis lacus ut leo molestie pellentesque. Nunc id congue risus. Donec sagittis erat nunc, non consectetur erat euismod eu. Nam at velit nisl. \ No newline at end of file diff --git a/nitrite-mvstore-adapter/build.gradle b/nitrite-mvstore-adapter/build.gradle index 696a49589..00d054e78 100644 --- a/nitrite-mvstore-adapter/build.gradle +++ b/nitrite-mvstore-adapter/build.gradle @@ -52,6 +52,7 @@ dependencies { testImplementation "uk.co.jemos.podam:podam:7.2.5.RELEASE" testImplementation "com.github.javafaker:javafaker:1.0.2" testImplementation "junit:junit:4.13.1" + testImplementation "org.mockito:mockito-core:3.9.0" testImplementation "org.apache.lucene:lucene-core:8.6.3" testImplementation "org.apache.lucene:lucene-analyzers-common:8.6.3" testImplementation "org.apache.lucene:lucene-queryparser:8.6.3" @@ -62,6 +63,7 @@ dependencies { testImplementation "org.meanbean:meanbean:2.0.3" testImplementation "com.fasterxml.jackson.core:jackson-databind:2.11.3" testImplementation "commons-io:commons-io:2.8.0" + testImplementation "com.google.guava:guava:29.0-jre" } test { diff --git a/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/MVStoreModule.java b/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/MVStoreModule.java index 5bf41152e..9270206e7 100644 --- a/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/MVStoreModule.java +++ b/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/MVStoreModule.java @@ -18,13 +18,15 @@ import lombok.AccessLevel; import lombok.Setter; -import org.dizitart.no2.module.NitriteModule; -import org.dizitart.no2.module.NitritePlugin; +import org.dizitart.no2.common.module.NitriteModule; +import org.dizitart.no2.common.module.NitritePlugin; import org.dizitart.no2.store.NitriteStore; import org.dizitart.no2.store.StoreModule; import java.util.Set; +import static org.dizitart.no2.common.util.Iterables.setOf; + /** * A {@link NitriteModule} which provides h2's mvstore as a storage engine. * diff --git a/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/NitriteMVMap.java b/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/NitriteMVMap.java index 6e56eb5aa..480685aab 100644 --- a/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/NitriteMVMap.java +++ b/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/NitriteMVMap.java @@ -79,7 +79,7 @@ public Value remove(Key key) { } @Override - public RecordStream keySet() { + public RecordStream keys() { return RecordStream.fromIterable(mvMap.keySet()); } @@ -121,6 +121,11 @@ public Pair next() { }; } + @Override + public RecordStream> reversedEntries() { + return () -> new ReverseIterator<>(mvMap); + } + @Override public Key higherKey(Key key) { return mvMap.higherKey(key); @@ -148,11 +153,12 @@ public boolean isEmpty() { @Override public void drop() { + nitriteStore.closeMap(getName()); nitriteStore.removeMap(getName()); } @Override public void close() { - // nothing to close + nitriteStore.closeMap(getName()); } } diff --git a/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/NitriteMVRTreeMap.java b/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/NitriteMVRTreeMap.java index cbf7de411..289a13be4 100644 --- a/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/NitriteMVRTreeMap.java +++ b/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/NitriteMVRTreeMap.java @@ -20,6 +20,7 @@ import org.dizitart.no2.common.RecordStream; import org.dizitart.no2.index.BoundingBox; import org.dizitart.no2.store.NitriteRTree; +import org.dizitart.no2.store.NitriteStore; import org.h2.mvstore.rtree.MVRTreeMap; import org.h2.mvstore.rtree.SpatialKey; @@ -29,12 +30,13 @@ * @since 1.0 * @author Anindya Chatterjee */ -class NitriteMVRTreeMap - implements NitriteRTree { +class NitriteMVRTreeMap implements NitriteRTree { private final MVRTreeMap mvMap; + private final NitriteStore nitriteStore; - NitriteMVRTreeMap(MVRTreeMap mvMap) { + NitriteMVRTreeMap(MVRTreeMap mvMap, NitriteStore nitriteStore) { this.mvMap = mvMap; + this.nitriteStore = nitriteStore; } @Override @@ -73,8 +75,12 @@ public long size() { } private SpatialKey getKey(Key key, long id) { - return new SpatialKey(id, key.getMinX(), - key.getMaxX(), key.getMinY(), key.getMaxY()); + if (key == null) { + return new SpatialKey(id); + } else { + return new SpatialKey(id, key.getMinX(), + key.getMaxX(), key.getMinY(), key.getMaxY()); + } } private RecordStream getRecordStream(MVRTreeMap.RTreeCursor treeCursor) { @@ -91,4 +97,21 @@ public NitriteId next() { } }); } + + @Override + public void close() { + nitriteStore.closeRTree(mvMap.getName()); + } + + @Override + public void clear() { + mvMap.clear(); + } + + @Override + public void drop() { + mvMap.clear(); + nitriteStore.closeRTree(mvMap.getName()); + nitriteStore.removeRTree(mvMap.getName()); + } } diff --git a/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/NitriteMVStore.java b/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/NitriteMVStore.java index f78cd26d7..db963d23d 100644 --- a/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/NitriteMVStore.java +++ b/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/NitriteMVStore.java @@ -39,10 +39,12 @@ public class NitriteMVStore extends AbstractNitriteStore { private MVStore mvStore; private final Map> nitriteMapRegistry; + private final Map> nitriteRTreeMapRegistry; public NitriteMVStore() { super(); this.nitriteMapRegistry = new ConcurrentHashMap<>(); + this.nitriteRTreeMapRegistry = new ConcurrentHashMap<>(); } @Override @@ -74,10 +76,23 @@ public void commit() { } @Override - public void close() { + public void close() throws Exception { if (getStoreConfig().autoCompact()) { compact(); } + + // close nitrite maps + for (NitriteMap nitriteMap : nitriteMapRegistry.values()) { + nitriteMap.close(); + } + + for (NitriteRTree rTree : nitriteRTreeMapRegistry.values()) { + rTree.close(); + } + + nitriteMapRegistry.clear(); + nitriteRTreeMapRegistry.clear(); + mvStore.close(); alert(StoreEvents.Closed); } @@ -100,6 +115,16 @@ public NitriteMap openMap(String mapName, Class keyT return nitriteMVMap; } + @Override + public void closeMap(String mapName) { + nitriteMapRegistry.remove(mapName); + } + + @Override + public void closeRTree(String rTreeName) { + nitriteRTreeMapRegistry.remove(rTreeName); + } + @Override public void removeMap(String name) { MVMap mvMap = mvStore.openMap(name); @@ -109,9 +134,15 @@ public void removeMap(String name) { @Override @SuppressWarnings({"unchecked", "rawtypes"}) - public NitriteRTree openRTree(String name, Class keyType, Class valueType) { - MVRTreeMap map = mvStore.openMap(name, new MVRTreeMap.Builder<>()); - return new NitriteMVRTreeMap(map); + public NitriteRTree openRTree(String mapName, Class keyType, Class valueType) { + if (nitriteRTreeMapRegistry.containsKey(mapName)) { + return (NitriteMVRTreeMap) nitriteRTreeMapRegistry.get(mapName); + } + + MVRTreeMap map = mvStore.openMap(mapName, new MVRTreeMap.Builder<>()); + NitriteMVRTreeMap nitriteMVRTreeMap = new NitriteMVRTreeMap(map, this); + nitriteRTreeMapRegistry.put(mapName, nitriteMVRTreeMap); + return nitriteMVRTreeMap; } @Override diff --git a/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/ReverseIterator.java b/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/ReverseIterator.java new file mode 100644 index 000000000..f98c0fae0 --- /dev/null +++ b/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/ReverseIterator.java @@ -0,0 +1,42 @@ +package org.dizitart.no2.mvstore; + +import org.dizitart.no2.common.tuples.Pair; +import org.h2.mvstore.MVMap; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * @author Anindya Chatterjee + */ +public class ReverseIterator implements Iterator> { + private final MVMap mvMap; + private Key anchor; + private boolean started; + + public ReverseIterator(MVMap mvMap) { + long version = mvMap.getVersion(); + this.mvMap = mvMap.openVersion(version); + this.anchor = this.mvMap.lastKey(); + this.started = false; + } + + @Override + public boolean hasNext() { + Key key = started ? mvMap.lowerKey(this.anchor) : mvMap.floorKey(this.anchor); + return key != null; + } + + @Override + public Pair next() { + Key key = started ? mvMap.lowerKey(this.anchor) : mvMap.floorKey(this.anchor); + this.started = true; + if (key == null) { + throw new NoSuchElementException(); + } + + Value value = mvMap.get(key); + this.anchor = key; + return new Pair<>(key, value); + } +} diff --git a/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/compat/v3/MigrationUtil.java b/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/compat/v3/MigrationUtil.java index 138c8888c..f6dc0d984 100644 --- a/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/compat/v3/MigrationUtil.java +++ b/nitrite-mvstore-adapter/src/main/java/org/dizitart/no2/mvstore/compat/v3/MigrationUtil.java @@ -19,9 +19,12 @@ import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.collection.meta.Attributes; +import org.dizitart.no2.common.DBNull; +import org.dizitart.no2.common.Fields; import org.dizitart.no2.exceptions.NitriteIOException; import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.index.IndexEntry; +import org.dizitart.no2.index.DBValue; +import org.dizitart.no2.index.IndexDescriptor; import org.dizitart.no2.index.IndexMeta; import org.dizitart.no2.store.UserCredential; import org.h2.mvstore.MVMap; @@ -29,7 +32,9 @@ import java.util.*; import java.util.concurrent.ConcurrentSkipListSet; +import java.util.concurrent.CopyOnWriteArrayList; +import static org.dizitart.no2.common.Constants.INDEX_PREFIX; import static org.dizitart.no2.common.Constants.STORE_INFO; import static org.dizitart.no2.common.util.ObjectUtils.convertToObjectArray; @@ -76,6 +81,9 @@ private static void copyData(MVMap oldMap, MVMap newMap) { Object newKey = key; if (key instanceof Compat.NitriteId) { newKey = nitriteId((Compat.NitriteId) key); + } else if (oldMap.getName().contains(INDEX_PREFIX)) { + // index map, wrap with DBValue + newKey = newKey == null ? DBNull.getInstance() : new DBValue((Comparable) newKey); } Object value = oldMap.get(key); @@ -88,19 +96,26 @@ private static void copyData(MVMap oldMap, MVMap newMap) { private static Object migrateValue(Object value) { if (value != null) { if (value instanceof Compat.UserCredential) { + // old user credentials return credential((Compat.UserCredential) value); } else if (value instanceof Compat.NitriteId) { + // old nitrite id return nitriteId((Compat.NitriteId) value); } else if (value instanceof Compat.Index) { + // old index entry return indexEntry((Compat.Index) value); } else if (value instanceof Compat.IndexMeta) { + // old index meta data return indexMeta((Compat.IndexMeta) value); } else if (value instanceof Compat.Document) { + // old document return document((Compat.Document) value); } else if (value instanceof Compat.Attributes) { + // old attribute return attributes((Compat.Attributes) value); } else if (value instanceof ConcurrentSkipListSet) { - return skipList((ConcurrentSkipListSet) value); + // old index nitrite id list + return arrayList((ConcurrentSkipListSet) value); } else if (value instanceof Iterable) { return iterable((Iterable) value); } else if (value.getClass().isArray()) { @@ -137,8 +152,8 @@ private static Iterable iterable(Iterable value) { return collection; } - private static ConcurrentSkipListSet skipList(ConcurrentSkipListSet value) { - ConcurrentSkipListSet newList = new ConcurrentSkipListSet<>(); + private static CopyOnWriteArrayList arrayList(ConcurrentSkipListSet value) { + CopyOnWriteArrayList newList = new CopyOnWriteArrayList<>(); for (Object object : value) { Object newValue = migrateValue(object); newList.add(newValue); @@ -175,19 +190,19 @@ private static Document document(Compat.Document value) { private static IndexMeta indexMeta(Compat.IndexMeta value) { Compat.Index index = value.getIndex(); - IndexEntry indexEntry = indexEntry(index); + IndexDescriptor indexDescriptor = indexEntry(index); IndexMeta indexMeta = new IndexMeta(); - indexMeta.setIndexEntry(indexEntry); + indexMeta.setIndexDescriptor(indexDescriptor); indexMeta.setIndexMap(value.getIndexMap()); indexMeta.setIsDirty(value.getIsDirty()); return indexMeta; } - private static IndexEntry indexEntry(Compat.Index value) { + private static IndexDescriptor indexEntry(Compat.Index value) { String indexType = value.getIndexType().name(); - return new IndexEntry(indexType, value.getField(), value.getCollectionName()); + return new IndexDescriptor(indexType, Fields.withNames(value.getField()), value.getCollectionName()); } private static NitriteId nitriteId(Compat.NitriteId value) { diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/CollectionFieldIndexTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/CollectionFieldIndexTest.java deleted file mode 100644 index 44ff99c11..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/CollectionFieldIndexTest.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.index.IndexType; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import static org.dizitart.no2.TestUtil.createDb; -import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee - */ -public class CollectionFieldIndexTest { - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - db = createDb(); - } - - @Test - public void testCollection() { - Document doc1 = Document.createDocument("name", "Anindya") - .put("color", new String[]{"red", "green", "blue"}) - .put("books", new Document[]{ - Document.createDocument("name", "Book ABCD") - .put("tag", new String[]{"tag1", "tag2"}), - Document.createDocument("name", "Book EFGH") - .put("tag", new String[]{"tag3", "tag1"}), - Document.createDocument("name", "No Tag") - }); - - Document doc2 = Document.createDocument("name", "Bill") - .put("color", new String[]{"purple", "yellow", "gray"}) - .put("books", new Document[]{ - Document.createDocument("name", "Book abcd") - .put("tag", new String[]{"tag4", "tag5"}), - Document.createDocument("name", "Book wxyz") - .put("tag", new String[]{"tag3", "tag1"}), - Document.createDocument("name", "No Tag 2") - }); - - Document doc3 = Document.createDocument("name", "John") - .put("color", new String[]{"black", "sky", "violet"}) - .put("books", new Document[]{ - Document.createDocument("name", "Book Mnop") - .put("tag", new String[]{"tag6", "tag2"}), - Document.createDocument("name", "Book ghij") - .put("tag", new String[]{"tag3", "tag7"}), - Document.createDocument("name", "No Tag") - }); - - NitriteCollection collection = db.getCollection("test"); - collection.createIndex("color", indexOptions(IndexType.Unique)); - collection.createIndex("books.tag", indexOptions(IndexType.NonUnique)); - collection.createIndex("books.name", indexOptions(IndexType.Fulltext)); - - WriteResult writeResult = collection.insert(doc1, doc2, doc3); - assertEquals(writeResult.getAffectedCount(), 3); - - DocumentCursor documents = collection.find(where("color").eq("red")); - assertTrue(isSimilar(documents.firstOrNull(), doc1, "name", "color", "books")); - - documents = collection.find(where("books.name").text("abcd")); - assertEquals(documents.size(), 2); - - documents = collection.find(where("books.tag").eq("tag2")); - assertEquals(documents.size(), 2); - - documents = collection.find(where("books.tag").eq("tag5")); - assertEquals(documents.size(), 1); - - documents = collection.find(where("books.tag").eq("tag10")); - assertEquals(documents.size(), 0); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/CustomFilterTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/CustomFilterTest.java deleted file mode 100644 index 518a1b56b..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/CustomFilterTest.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.dizitart.no2.collection.BaseCollectionTest; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.index.IndexType; -import org.junit.Test; - -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class CustomFilterTest extends BaseCollectionTest { - - @Test - public void testCustomFilter() { - insert(); - collection.createIndex("firstName", indexOptions(IndexType.NonUnique)); - DocumentCursor cursor = collection.find(element -> element.getSecond().get("firstName", String.class) - .equalsIgnoreCase("FN1")); - - assertEquals(cursor.size(), 1); - assertEquals(cursor.firstOrNull().get("firstName"), "fn1"); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/DbTestOperations.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/DbTestOperations.java deleted file mode 100644 index 669ee0310..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/DbTestOperations.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.index.IndexType; -import org.junit.Rule; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.*; - -import static org.dizitart.no2.TestUtil.isSorted; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee. - */ -public class DbTestOperations { - private final String fileName = getRandomTempDbFile(); - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - public static String getRandomTempDbFile() { - String dataDir = System.getProperty("java.io.tmpdir") + File.separator + "nitrite" + File.separator + "data"; - File file = new File(dataDir); - if (!file.exists()) { - assertTrue(file.mkdirs()); - } - return file.getPath() + File.separator + UUID.randomUUID().toString() + ".db"; - } - - void createDb() { - db = TestUtil.createDb(fileName); - db.close(); - } - - void writeCollection() { - NitriteCollection collection; - - db = TestUtil.createDb(fileName); - - collection = db.getCollection("test"); - collection.remove(ALL); - db.close(); - } - - void writeIndex() { - NitriteCollection collection; - - db = TestUtil.createDb(fileName); - - collection = db.getCollection("test"); - collection.remove(ALL); - collection.createIndex("body", indexOptions(IndexType.Fulltext)); - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - db.close(); - } - - void insertInCollection() throws ParseException { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); - - Document doc1 = createDocument("firstName", "fn1") - .put("lastName", "ln1") - .put("birthDay", simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) - .put("data", new byte[]{1, 2, 3}) - .put("body", "a quick brown fox jump over the lazy dog"); - Document doc2 = createDocument("firstName", "fn2") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2010-06-12T16:02:48.440Z")) - .put("data", new byte[]{3, 4, 3}) - .put("body", "quick hello world from nitrite"); - Document doc3 = createDocument("firstName", "fn3") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2014-04-17T16:02:48.440Z")) - .put("data", new byte[]{9, 4, 8}) - .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + - "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); - - NitriteCollection collection; - - db = TestUtil.createDb(fileName); - - collection = db.getCollection("test"); - - WriteResult result = collection.insert(doc1, doc2, doc3); - assertEquals(result.getAffectedCount(), 3); - - db.commit(); - db.close(); - } - - void readCollection() throws ParseException { - NitriteCollection collection; - - db = TestUtil.createDb(fileName); - - collection = db.getCollection("test"); - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").gt(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").gte(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lt(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lte(new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").lt(new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").gt(new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").gte(new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").lte(new Date()).and(where("firstName").eq("fn1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte(new Date()).or(where("firstName").eq("fn12"))); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1")) - .not()); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").eq((byte) 4)); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").lt(4)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("firstName").notIn("fn1", "fn2")); - assertEquals(cursor.size(), 1); - - collection.createIndex("birthDay", indexOptions(IndexType.Unique)); - cursor = collection.find().sort("birthDay", SortOrder.Descending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, false)); - - cursor = collection.find(where("body").text("Lorem")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("body").text("quick")); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("body").text("nosql")); - assertEquals(cursor.size(), 0); - - db.close(); - } - - void deleteDb() throws IOException { - if (db != null && !db.isClosed()) { - db.close(); - } - Files.delete(Paths.get(fileName)); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/DbWriteCloseReadTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/DbWriteCloseReadTest.java deleted file mode 100644 index 5a3a8b10c..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/DbWriteCloseReadTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.junit.Rule; -import org.junit.Test; - -import java.text.ParseException; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * @author Anindya Chatterjee. - */ -public class DbWriteCloseReadTest { - private final DbTestOperations operations = new DbTestOperations(); - private volatile boolean writeCompleted = false; - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testWriteCloseRead() throws Exception { - try { - operations.createDb(); - operations.writeCollection(); - operations.writeIndex(); - operations.insertInCollection(); - } catch (ParseException pe) { - // ignore - } finally { - writeCompleted = true; - } - - try { - assertTrue(writeCompleted); - operations.readCollection(); - } catch (Exception e) { - fail("collection read failed - " + e.getMessage()); - } finally { - operations.deleteDb(); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/DocumentMetadataTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/DocumentMetadataTest.java deleted file mode 100644 index 3a912de78..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/DocumentMetadataTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.dizitart.no2.collection.BaseCollectionTest; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.events.EventType; -import org.junit.Test; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee. - */ -public class DocumentMetadataTest extends BaseCollectionTest { - @Test - public void testTimeStamp() { - Document document = createDocument("test_key", "test_value"); - assertEquals(document.getRevision().intValue(), 0); - assertEquals(document.getLastModifiedSinceEpoch().longValue(), 0L); - - collection.insert(document); - document = collection.find().firstOrNull(); - - assertEquals(document.getRevision().intValue(), 1); - assertTrue(document.getLastModifiedSinceEpoch() > 0); - - long previous = document.getRevision(); - - DocumentCursor cursor = collection.find(where("test_key").eq("test_value")); - document = cursor.firstOrNull(); - document.put("another_key", "another_value"); - - collection.update(document); - cursor = collection.find(where("test_key").eq("test_value")); - document = cursor.firstOrNull(); - - assertTrue(document.getRevision() > previous); - - final long time = document.getRevision(); - final Document removed = document; - - collection.subscribe(changeInfo -> { - if (changeInfo.getEventType() == EventType.Remove) { - assertTrue(removed.getRevision() > time); - } - }); - - collection.remove(document); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/MultiThreadedTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/MultiThreadedTest.java deleted file mode 100644 index 3bdc5de9e..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/MultiThreadedTest.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.concurrent.ThreadPoolManager; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.io.File; -import java.util.*; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.TestUtil.createDb; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - - -/** - * @author Anindya Chatterjee. - */ -@RunWith(Parameterized.class) -public class MultiThreadedTest { - private static final String fileName = getRandomTempDbFile(); - @Parameterized.Parameter - public boolean inMemory = false; - private NitriteCollection collection; - private final int threadCount = 20; - private final CountDownLatch latch = new CountDownLatch(threadCount); - private final int iterationCount = 100; - private final Random generator = new Random(); - private final AtomicInteger docCounter = new AtomicInteger(0); - private ExecutorService executor = ThreadPoolManager.getThreadPool(threadCount, "MultiThreadedTest"); - private Nitrite db; - - @Parameterized.Parameters(name = "InMemory = {0}") - public static Collection data() { - return Arrays.asList(new Object[][]{ - {false}, - {true} - }); - } - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testOperations() throws InterruptedException { - db = inMemory ? createDb() : createDb(fileName); - - collection = db.getCollection("test"); - collection.remove(Filter.ALL); - collection.createIndex("unixTime", IndexOptions.indexOptions(IndexType.Unique)); - db.commit(); - - for (int i = 0; i < threadCount; i++) { - executor.submit(() -> { - for (int j = 0; j < iterationCount; j++) { - try { - Document document = generate(); - collection.insert(document); - - if (j == iterationCount / 2 - && !collection.hasIndex("text") - && !collection.hasIndex("date")) { - collection.createIndex("text", IndexOptions.indexOptions(IndexType.Fulltext)); - collection.createIndex("date", IndexOptions.indexOptions(IndexType.NonUnique)); - } - - long unixTime = (long) document.get("unixTime"); - DocumentCursor cursor = collection.find(where("unixTime").eq(unixTime)); - assertTrue(cursor.size() >= 0); - - if (collection.hasIndex("text") && !collection.isIndexing("text")) { - String textData = (String) document.get("text"); - cursor = collection.find(where("text").text(textData)); - assertTrue(cursor.size() >= 0); - } - - assertTrue(collection.hasIndex("unixTime")); - } catch (Throwable e) { - System.out.println("Exception at thread " + - Thread.currentThread().getName() + " with iteration " + j); - e.printStackTrace(); - } - } - latch.countDown(); - }); - } - - latch.await(); - - db.commit(); - - assertTrue(collection.hasIndex("text")); - assertTrue(collection.hasIndex("date")); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), docCounter.get()); - - cursor = collection.find(where("unixTime").gt(1L)); - assertEquals(cursor.size(), docCounter.get()); - - db.close(); - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - - if (!inMemory) { - File dbFile = new File(fileName); - long fileSize = dbFile.length(); - assertTrue(fileSize > 0); - dbFile.delete(); - } - - if (executor != null && !executor.isShutdown()) { - executor.shutdown(); - executor = null; - } - } - - private synchronized Document generate() { - Document document = createDocument("unixTime", System.nanoTime() + docCounter.incrementAndGet()); - byte[] blob = new byte[1024]; - generator.nextBytes(blob); - document.put("blob", blob); - document.put("text", UUID.randomUUID().toString().replaceAll("-", " ")); - document.put("date", new Date()); - return document; - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteBuilderNegativeTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteBuilderNegativeTest.java deleted file mode 100644 index b93aea6fd..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteBuilderNegativeTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.apache.commons.io.FileUtils; -import org.dizitart.no2.common.util.StringUtils; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.mvstore.MVStoreModule; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.io.File; - -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.TestUtil.createDb; - -/** - * @author Anindya Chatterjee. - */ -public class NitriteBuilderNegativeTest { - private Nitrite db; - private String filePath; - - @Rule - public Retry retry = new Retry(3); - - @Test(expected = NitriteIOException.class) - public void testCreateReadonlyDatabase() { - filePath = getRandomTempDbFile(); - - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(filePath) - .readOnly(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .openOrCreate(); - db.close(); - } - - @Test(expected = InvalidOperationException.class) - public void testCreateReadonlyInMemoryDatabase() { - MVStoreModule storeModule = MVStoreModule.withConfig() - .readOnly(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .openOrCreate(); - db.close(); - } - - @Test(expected = NitriteIOException.class) - public void testOpenWithLock() { - filePath = getRandomTempDbFile(); - - db = createDb(filePath); - db = createDb(filePath); - } - - @Test(expected = NitriteIOException.class) - public void testInvalidDirectory() { - filePath = "/ytgr/hfurh/frij.db"; - db = createDb(filePath); - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - - if (!StringUtils.isNullOrEmpty(filePath)) { - FileUtils.deleteQuietly(new File(filePath)); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteBuilderTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteBuilderTest.java deleted file mode 100644 index eabd8d511..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteBuilderTest.java +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.SecurityException; -import org.dizitart.no2.index.Indexer; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.mvstore.MVStoreConfig; -import org.dizitart.no2.mvstore.MVStoreModule; -import org.dizitart.no2.mvstore.MVStoreModuleBuilder; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.store.NitriteMap; -import org.dizitart.no2.store.StoreConfig; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Random; - -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.TestUtil.createDb; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.common.util.StringUtils.isNullOrEmpty; -import static org.dizitart.no2.module.NitriteModule.module; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class NitriteBuilderTest { - private String fakeFile; - private String filePath; - private Nitrite db; - private Nitrite fakeDb; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void startup() { - fakeFile = getRandomTempDbFile(); - filePath = getRandomTempDbFile(); - } - - @After - public void cleanup() throws IOException { - (new NitriteConfig()).fieldSeparator("."); - - if (db != null && !db.isClosed()) { - db.close(); - } - - if (Files.exists(Paths.get(filePath))) { - Files.delete(Paths.get(filePath)); - } - - if (fakeDb != null && !fakeDb.isClosed()){ - fakeDb.close(); - } - - if (Files.exists(Paths.get(fakeFile))) { - Files.delete(Paths.get(fakeFile)); - } - } - - @Test - public void testConfig() throws IOException { - MVStoreModuleBuilder builder = MVStoreModule.withConfig(); - builder.autoCommitBufferSize(1); - builder.compress(true); - builder.autoCommit(false); - builder.filePath(filePath); - - NitriteBuilder nitriteBuilder = Nitrite.builder(); - nitriteBuilder.loadModule(module(new CustomIndexer())); - nitriteBuilder.loadModule(builder.build()); - - db = nitriteBuilder.openOrCreate(); - NitriteConfig config = nitriteBuilder.getNitriteConfig(); - MVStoreConfig storeConfig = (MVStoreConfig) db.getStore().getStoreConfig(); - - assertEquals(storeConfig.autoCommitBufferSize(), 1); - assertEquals(config.findIndexer("Custom").getClass(), CustomIndexer.class); - assertFalse(storeConfig.autoCommit()); - assertFalse(storeConfig.autoCompact()); - assertTrue(storeConfig.compress()); - assertFalse(storeConfig.isReadOnly()); - assertFalse(storeConfig.isInMemory()); - assertFalse(isNullOrEmpty(storeConfig.filePath())); - - db.close(); - - builder = MVStoreModule.withConfig() - .readOnly(true) - .filePath(filePath); - - db = Nitrite.builder().loadModule(builder.build()).openOrCreate(); - - storeConfig = (MVStoreConfig) db.getStore().getStoreConfig(); - assertTrue(storeConfig.isReadOnly()); - db.close(); - - Files.delete(Paths.get(filePath)); - } - - @Test - public void testConfigWithFile() { - File file = new File(filePath); - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(file) - .compress(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .openOrCreate(); - StoreConfig storeConfig = db.getStore().getStoreConfig(); - - assertFalse(storeConfig.isInMemory()); - assertFalse(isNullOrEmpty(storeConfig.filePath())); - - NitriteCollection test = db.getCollection("test"); - assertNotNull(test); - - db.commit(); - db.close(); - - assertTrue(file.delete()); - } - - @Test - public void testConfigWithFileNull() { - File file = null; - MVStoreModule module = MVStoreModule.withConfig() - .filePath(file) - .build(); - - db = Nitrite.builder().loadModule(module).openOrCreate(); - StoreConfig storeConfig = db.getStore().getStoreConfig(); - - assertTrue(storeConfig.isInMemory()); - assertTrue(isNullOrEmpty(storeConfig.filePath())); - - NitriteCollection test = db.getCollection("test"); - assertNotNull(test); - - db.commit(); - db.close(); - } - - @Test - public void testPopulateRepositories() { - File file = new File(filePath); - MVStoreModule module = MVStoreModule.withConfig().filePath(file).build(); - db = Nitrite.builder() - .fieldSeparator(".") - .loadModule(module) - .openOrCreate(); - - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("id1", "value")); - - ObjectRepository repository = db.getRepository(TestObject.class); - repository.insert(new TestObject("test", 1L)); - - ObjectRepository repository2 = db.getRepository(TestObject.class, "key"); - TestObject object = new TestObject(); - object.stringValue = "test2"; - object.longValue = 2L; - repository2.insert(object); - - ObjectRepository repository3 = db.getRepository(TestObject2.class, "key"); - TestObject2 object2 = new TestObject2(); - object2.stringValue = "test2"; - object2.longValue = 2L; - repository3.insert(object2); - - db.commit(); - db.close(); - - db = Nitrite.builder() - .loadModule(module) - .fieldSeparator(".") - .openOrCreate(); - assertTrue(db.hasCollection("test")); - assertTrue(db.hasRepository(TestObject.class)); - assertTrue(db.hasRepository(TestObject.class, "key")); - assertFalse(db.hasRepository(TestObject2.class)); - assertTrue(db.hasRepository(TestObject2.class, "key")); - } - - - @Test - public void testNitriteMapper() { - NitriteBuilder builder = Nitrite.builder(); - builder.loadModule(module(new CustomNitriteMapper())); - NitriteConfig config = builder.getNitriteConfig(); - assertNotNull(config.nitriteMapper()); - } - - @Test(expected = SecurityException.class) - public void testOpenOrCreateNullUserId() { - NitriteBuilder builder = Nitrite.builder(); - builder.openOrCreate(null, "abcd"); - } - - @Test(expected = SecurityException.class) - public void testOpenOrCreateNullPassword() { - NitriteBuilder builder = Nitrite.builder(); - builder.openOrCreate("abcd", null); - } - - @Test(expected = NitriteIOException.class) - public void testDbCorruption() throws IOException { - File file = new File(fakeFile); - FileWriter writesToFile; - // Create file writer object - writesToFile = new FileWriter(file); - // Wrap the writer with buffered streams - BufferedWriter writer = new BufferedWriter(writesToFile); - int line; - Random rand = new Random(); - for (int j = 0; j < 10; j++) { - // Randomize an integer and write it to the output file - line = rand.nextInt(50000); - writer.write(line + "\n"); - } - // Close the stream - writer.close(); - - fakeDb = createDb(fakeFile); - assertNull(fakeDb); - } - - @Test(expected = InvalidOperationException.class) - public void testDbInMemoryReadonly() { - MVStoreModule module = MVStoreModule.withConfig() - .readOnly(true) - .build(); - - fakeDb = Nitrite.builder() - .loadModule(module) - .openOrCreate(); - assertNull(fakeDb); - } - - @Test(expected = NitriteIOException.class) - public void testDbInvalidDirectory() { - fakeFile = System.getProperty("java.io.tmpdir") + File.separator + "fake" + File.separator + "fake.db"; - db = createDb(fakeFile, "test", "test"); - assertNull(db); - } - - @Test - public void testFieldSeparator() { - MVStoreModule module = MVStoreModule.withConfig() - .filePath(filePath) - .build(); - db = Nitrite.builder() - .loadModule(module) - .fieldSeparator("::") - .openOrCreate(); - - Document document = createDocument("firstName", "John") - .put("colorCodes", new Document[]{createDocument("color", "Red"), createDocument("color", "Green")}) - .put("address", createDocument("street", "ABCD Road")); - - String street = document.get("address::street", String.class); - assertEquals("ABCD Road", street); - - // use default separator, it should return null - street = document.get("address.street", String.class); - assertNull(street); - - assertEquals(document.get("colorCodes::1::color"), "Green"); - } - - @Test(expected = NitriteIOException.class) - public void testInvalidPath() { - MVStoreModule module = MVStoreModule.withConfig() - .filePath("http://www.localhost.com") - .build(); - - db = Nitrite.builder() - .loadModule(module) - .openOrCreate("test", "test"); - assertNull(db); - } - - private static class CustomIndexer implements Indexer { - - @Override - public String getIndexType() { - return "Custom"; - } - - @Override - public void writeIndex(NitriteMap collection, NitriteId nitriteId, String field, Object fieldValue) { - - } - - @Override - public void removeIndex(NitriteMap collection, NitriteId nitriteId, String field, Object fieldValue) { - - } - - @Override - public void updateIndex(NitriteMap collection, NitriteId nitriteId, String field, Object newValue, Object oldValue) { - - } - - @Override - public void dropIndex(NitriteMap collection, String field) { - - } - - @Override - public Indexer clone() throws CloneNotSupportedException { - return null; - } - - @Override - public void initialize(NitriteConfig nitriteConfig) { - - } - } - - public static class CustomNitriteMapper implements NitriteMapper { - - @Override - public Target convert(Source source, Class type) { - return null; - } - - @Override - public boolean isValueType(Class type) { - return false; - } - - @Override - public boolean isValue(Object object) { - return false; - } - - @Override - public void initialize(NitriteConfig nitriteConfig) { - - } - } - - @Index(value = "longValue") - private static class TestObject implements Mappable { - private String stringValue; - private Long longValue; - - public TestObject() { - } - - public TestObject(String stringValue, Long longValue) { - this.longValue = longValue; - this.stringValue = stringValue; - } - - @Override - public Document write(NitriteMapper mapper) { - return createDocument("stringValue", stringValue) - .put("longValue", longValue); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - if (document != null) { - this.stringValue = document.get("stringValue", String.class); - this.longValue = document.get("longValue", Long.class); - } - } - } - - @Index(value = "longValue") - private static class TestObject2 implements Mappable { - private String stringValue; - private Long longValue; - - public TestObject2() { - } - - public TestObject2(String stringValue, Long longValue) { - this.longValue = longValue; - this.stringValue = stringValue; - } - - @Override - public Document write(NitriteMapper mapper) { - return createDocument("stringValue", stringValue) - .put("longValue", longValue); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - if (document != null) { - this.stringValue = document.get("stringValue", String.class); - this.longValue = document.get("longValue", Long.class); - } - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteCorruptedTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteCorruptedTest.java deleted file mode 100644 index a68214245..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteCorruptedTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.concurrent.ThreadPoolManager; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.concurrent.ExecutorService; - -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.TestUtil.createDb; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee - */ -public class NitriteCorruptedTest { - private Nitrite db; - private NitriteCollection collection; - private final String fileName = getRandomTempDbFile(); - private Thread thread; - private final ExecutorService dbPool = ThreadPoolManager.getThreadPool(Runtime.getRuntime().availableProcessors(), - "NitriteCorruptedTest"); - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - db = createDb(fileName); - - collection = db.getCollection("test"); - collection.remove(ALL); - - thread = new Thread(() -> { - for (int i = 0; i < 50000; i++) { - - // Interruption Guard - if (Thread.interrupted()) { - break; - } - - Document doc1 = createDocument(String.valueOf(System.currentTimeMillis()), "fn1") - .put("lastName", "ln1") - .put("data", new byte[]{1, 2, 3}) - .put("body", "a quick brown fox jump over the lazy dog"); - - // Separate user thread from Db write thread - dbPool.submit(() -> collection.insert(doc1)); - } - }); - } - - @After - public void tearDown() throws IOException { - if (collection.isOpen()) { - collection.remove(ALL); - collection.close(); - } - db.close(); - Files.delete(Paths.get(fileName)); - } - - @Test(timeout = 10000) - public void issue118() throws InterruptedException { - thread.start(); - Thread.sleep(10); - thread.interrupt(); - Thread.sleep(500); - assertTrue(collection.isOpen()); - assertFalse(db.isClosed()); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteSecurityNegativeTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteSecurityNegativeTest.java deleted file mode 100644 index f7a28104e..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteSecurityNegativeTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.apache.commons.io.FileUtils; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.exceptions.NitriteException; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.io.File; - -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.TestUtil.createDb; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class NitriteSecurityNegativeTest { - private Nitrite db; - private final String fileName = getRandomTempDbFile(); - - @Rule - public Retry retry = new Retry(3); - - @Test(expected = NitriteException.class) - public void testOpenSecuredWithoutCredential() { - db = createDb(fileName, "test-user", "test-password"); - NitriteCollection dbCollection = db.getCollection("test"); - dbCollection.insert(createDocument("test", "test")); - db.commit(); - db.close(); - - db = createDb(fileName); - dbCollection = db.getCollection("test"); - assertEquals(dbCollection.find().size(), 1); - } - - @Test(expected = NitriteException.class) - public void testOpenUnsecuredWithCredential() { - db = createDb(fileName); - NitriteCollection dbCollection = db.getCollection("test"); - dbCollection.insert(createDocument("test", "test")); - db.commit(); - db.close(); - - db = createDb(fileName, "test-user", "test-password"); - dbCollection = db.getCollection("test"); - assertEquals(dbCollection.find().size(), 1); - } - - @Test(expected = NitriteException.class) - public void testWrongCredential() { - db = createDb(fileName, "test-user", "test-password"); - NitriteCollection dbCollection = db.getCollection("test"); - dbCollection.insert(createDocument("test", "test")); - db.commit(); - db.close(); - - db = createDb(fileName, "test-user", "test-password2"); - dbCollection = db.getCollection("test"); - assertEquals(dbCollection.find().size(), 1); - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - - FileUtils.deleteQuietly(new File(fileName)); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteSecurityTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteSecurityTest.java deleted file mode 100644 index f8901e416..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteSecurityTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.apache.commons.io.FileUtils; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.exceptions.SecurityException; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; - -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.TestUtil.createDb; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee. - */ -public class NitriteSecurityTest { - private Nitrite db; - private final String fileName = getRandomTempDbFile(); - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testSecured() throws IOException { - db = createDb(fileName, "test-user", "test-password"); - NitriteCollection dbCollection = db.getCollection("test"); - dbCollection.insert(createDocument("test", "test")); - db.commit(); - db.close(); - - db = createDb(fileName, "test-user", "test-password"); - dbCollection = db.getCollection("test"); - assertEquals(dbCollection.find().size(), 1); - db.close(); - Files.delete(Paths.get(fileName)); - } - - @Test - public void testUnsecured() throws IOException { - db = createDb(fileName); - NitriteCollection dbCollection = db.getCollection("test"); - dbCollection.insert(createDocument("test", "test")); - db.commit(); - db.close(); - - db = createDb(fileName); - dbCollection = db.getCollection("test"); - assertEquals(dbCollection.find().size(), 1); - db.close(); - Files.delete(Paths.get(fileName)); - } - - @Test - public void testInMemory() { - db = createDb("test-user", "test-password"); - NitriteCollection dbCollection = db.getCollection("test"); - dbCollection.insert(createDocument("test", "test")); - db.commit(); - assertEquals(dbCollection.find().size(), 1); - db.close(); - - db = createDb(); - dbCollection = db.getCollection("test"); - assertEquals(dbCollection.find().size(), 0); - db.close(); - } - - @Test - public void testIssue116() throws IOException { - db = createDb(fileName, "test-user", "test-password"); - db.close(); - try { - db = createDb(fileName,"test-user2", "test-password2"); - } catch (SecurityException se) { - db = createDb(fileName,"test-user", "test-password"); - assertNotNull(db); - } finally { - db.close(); - Files.delete(Paths.get(fileName)); - } - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - - FileUtils.deleteQuietly(new File(fileName)); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteStressTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteStressTest.java deleted file mode 100644 index 29e1dddc7..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteStressTest.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Id; -import org.junit.Rule; -import org.junit.Test; -import uk.co.jemos.podam.api.PodamFactory; -import uk.co.jemos.podam.api.PodamFactoryImpl; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlSchemaType; -import java.util.ArrayList; -import java.util.List; - -import static org.dizitart.no2.TestUtil.createDb; - - -/** - * @author Anindya Chatterjee - */ -public class NitriteStressTest { - private static final int TEST_SET_COUNT = 15000; - private final PodamFactory podamFactory = new PodamFactoryImpl(); - - @Rule - public Retry retry = new Retry(3); - - @Test - public void stressTest() { - Nitrite database = createDb(); - ObjectRepository testRepository = database.getRepository(TestDto.class); - testRepository.createIndex("lastName", IndexOptions.indexOptions(IndexType.Fulltext)); - testRepository.createIndex("birthDate", IndexOptions.indexOptions(IndexType.NonUnique)); - - int counter = 0; - try { - for (TestDto testDto : createTestSet()) { - testRepository.insert(testDto); - counter++; - } - } catch (Throwable t) { - System.err.println("Crashed after " + counter + " records"); - throw t; - } - } - - private List createTestSet() { - List testData = new ArrayList<>(); - for (int i = 0; i < TEST_SET_COUNT; i++) { - TestDto testRecords = podamFactory.manufacturePojo(TestDto.class); - testData.add(testRecords); - } - return testData; - } - - @Data - public static class TestDto implements Mappable { - - @XmlElement( - name = "StudentNumber", - required = true - ) - @Id - protected String studentNumber; - - @XmlElement( - name = "LastName", - required = true - ) - protected String lastName; - - @XmlElement( - name = "Prefixes" - ) - protected String prefixes; - - @XmlElement( - name = "Initials", - required = true - ) - protected String initials; - - @XmlElement( - name = "FirstNames" - ) - protected String firstNames; - @XmlElement( - name = "Nickname" - ) - protected String nickName; - - @XmlElement( - name = "BirthDate", - required = true - ) - @XmlSchemaType( - name = "date" - ) - protected String birthDate; - - - public TestDto() { - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("studentNumber", studentNumber) - .put("lastName", lastName) - .put("prefixes", prefixes) - .put("initials", initials) - .put("firstNames", firstNames) - .put("nickName", nickName) - .put("birthDate", birthDate); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - studentNumber = document.get("studentNumber", String.class); - lastName = document.get("lastName", String.class); - prefixes = document.get("prefixes", String.class); - initials = document.get("initials", String.class); - firstNames = document.get("firstNames", String.class); - nickName = document.get("nickName", String.class); - birthDate = document.get("birthDate", String.class); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteTest.java index 31849ffcb..d49a599cf 100644 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteTest.java +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/NitriteTest.java @@ -1,17 +1,18 @@ /* - * Copyright (c) 2017-2020. Nitrite author or authors. + * Copyright (c) 2017-2021 Nitrite author or authors. * * Licensed 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 + * 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.dizitart.no2; @@ -20,16 +21,20 @@ import lombok.Data; import lombok.NoArgsConstructor; import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.FindOptions; import org.dizitart.no2.collection.NitriteCollection; import org.dizitart.no2.collection.UpdateOptions; import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.common.WriteResult; import org.dizitart.no2.common.concurrent.ThreadPoolManager; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; import org.dizitart.no2.exceptions.NitriteIOException; import org.dizitart.no2.exceptions.ValidationException; import org.dizitart.no2.index.IndexOptions; import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.integration.TestUtil; import org.dizitart.no2.mvstore.MVStoreModule; import org.dizitart.no2.repository.ObjectRepository; import org.dizitart.no2.repository.annotations.Id; @@ -49,20 +54,18 @@ import java.nio.file.Paths; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.List; -import java.util.Locale; -import java.util.Random; -import java.util.Set; +import java.util.*; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; -import static java.nio.file.Paths.get; -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; import static org.dizitart.no2.collection.Document.createDocument; import static org.dizitart.no2.common.Constants.INTERNAL_NAME_SEPARATOR; import static org.dizitart.no2.common.Constants.META_MAP_NAME; import static org.dizitart.no2.filters.Filter.ALL; +import static org.dizitart.no2.filters.Filter.and; import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; import static org.junit.Assert.*; /** @@ -103,13 +106,13 @@ public void setUp() throws ParseException { collection = db.getCollection("test"); collection.remove(ALL); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.Unique)); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "firstName"); collection.insert(doc1, doc2, doc3); } @After - public void tearDown() throws IOException { + public void tearDown() { if (collection.isOpen()) { collection.remove(ALL); collection.close(); @@ -120,7 +123,7 @@ public void tearDown() throws IOException { } catch (NitriteIOException ignore) { } } - Files.delete(get(fileName)); + deleteDb(fileName); } @Test @@ -356,8 +359,8 @@ public void testIssue185() throws InterruptedException { }).start(); for (int i = 0; i < 1000; ++i) { - repository.find(where("status").eq(Receipt.Status.COMPLETED).not()) - .sort("createdTimestamp", SortOrder.Descending).toList(); + repository.find(where("status").eq(Receipt.Status.COMPLETED).not(), + FindOptions.orderBy("createdTimestamp", SortOrder.Descending)).toList(); try { Thread.sleep(50); } catch (InterruptedException ignored) { @@ -465,21 +468,21 @@ public void testReadCompatibility() throws IOException { NitriteCollection collection = db.getCollection("test"); // text filter has be the first filter in and clause - List cursor = collection.find(where("second_key").text("fox") - .and(where("first_key").eq(1))).toList(); + List cursor = collection.find( + and(where("second_key").text("fox"), where("first_key").eq(1))).toList(); assertEquals(cursor.size(), 1); assertEquals(cursor.get(0).get("third_key"), 0.5); ObjectRepository repository = db.getRepository(Receipt.class); ObjectRepository orangeRepository = db.getRepository(Receipt.class, "orange"); - List list = repository.find(where("synced").eq(true) - .and(where("status").eq(Receipt.Status.PREPARING.toString()))).toList(); + List list = repository.find( + and(where("synced").eq(true), where("status").eq(Receipt.Status.PREPARING.toString()))).toList(); assertEquals(list.size(), 1); assertEquals(list.get(0).clientRef, "1"); - list = orangeRepository.find(where("synced").eq(false) - .and(where("status").eq(Receipt.Status.PREPARING.toString()))).toList(); + list = orangeRepository.find( + and(where("synced").eq(false), where("status").eq(Receipt.Status.PREPARING.toString()))).toList(); assertEquals(list.size(), 0); assertNotNull(repository.getAttributes()); @@ -494,10 +497,10 @@ public void testIssue212() { Document doc = createDocument("fifth_key", "fifth_key"); if (!collection.hasIndex("key")) { - collection.createIndex("key", IndexOptions.indexOptions(IndexType.NonUnique)); + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "key"); } if (!collection.hasIndex("second_key")) { - collection.createIndex("second_key", IndexOptions.indexOptions(IndexType.NonUnique)); + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "second_key"); } collection.insert(doc1, doc2); @@ -509,6 +512,56 @@ public void testIssue212() { } } + @Test + public void testIssue245() throws Exception { + class ThreadRunner implements Runnable { + @Override + public void run() { + try { + long id = Thread.currentThread().getId(); + NitriteCollection collection = db.getCollection("testIssue245"); + + for (int i = 0; i < 5; i++) { + + System.out.println("Thread ID = " + id + " Inserting doc " + i); + Document doc = Document.createDocument(UUID.randomUUID().toString(), UUID.randomUUID().toString()); + + WriteResult result = collection.insert(doc);//db.commit(); + System.out.println("Result of insert = " + result.getAffectedCount()); + System.out.println("Thread id = " + id + " --> count = " + collection.size()); + + Thread.sleep(10); + + }//for closing + + collection.close(); + + } catch (Exception e) { + e.printStackTrace(); + } + } + }; + + Thread t0 = new Thread(new ThreadRunner()); + Thread t1 = new Thread(new ThreadRunner()); + Thread t2 = new Thread(new ThreadRunner()); + + t0.start(); + t1.start(); + t2.start(); + + Thread.sleep(10 * 1000); + + t0.join(); + t1.join(); + t2.join(); + + NitriteCollection collection = db.getCollection("testIssue245"); + System.out.println("No of Documents = " + collection.size()); + collection.close(); + db.close(); + } + @Data @AllArgsConstructor @NoArgsConstructor @@ -533,13 +586,13 @@ public void read(NitriteMapper mapper, Document document) { @NoArgsConstructor @AllArgsConstructor @Indices({ - @Index(value = "synced", type = IndexType.NonUnique) + @Index(value = "synced", type = IndexType.NON_UNIQUE) }) public static class Receipt implements Mappable { - private Status status; @Id private String clientRef; private Boolean synced; + private Status status; private Long createdTimestamp = System.currentTimeMillis(); @Override @@ -564,6 +617,7 @@ public void read(NitriteMapper mapper, Document document) { this.createdTimestamp = document.get("createdTimestamp", Long.class); } } + public enum Status { COMPLETED, PREPARING, diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/Retry.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/Retry.java deleted file mode 100644 index b9706d1a0..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/Retry.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.dizitart.no2; - -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; - -/** - * @author Anindya Chatterjee - */ -public class Retry implements TestRule { - private final int retryCount; - - public Retry(int retryCount) { - this.retryCount = retryCount; - } - - public Statement apply(Statement base, Description description) { - return statement(base, description); - } - - private Statement statement(final Statement base, final Description description) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - Throwable caughtThrowable = null; - - // implement retry logic here - for (int i = 0; i < retryCount; i++) { - try { - base.evaluate(); - return; - } catch (Throwable t) { - caughtThrowable = t; - System.err.println(description.getDisplayName() + ": run " + (i + 1) + " failed"); - } - } - System.err.println(description.getDisplayName() + ": giving up after " + retryCount + " failures"); - throw caughtThrowable; - } - }; - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/SerializabilityTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/SerializabilityTest.java deleted file mode 100644 index 31a165232..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/SerializabilityTest.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.exceptions.ValidationException; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.File; -import java.io.Serializable; - -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.TestUtil.createDb; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee - */ -public class SerializabilityTest { - private NitriteCollection collection; - private File dbFile; - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - dbFile = new File(getRandomTempDbFile()); - db = createDb(dbFile.getPath()); - collection = db.getCollection("test"); - } - - @After - public void tearDown() { - if (db != null && !db.isClosed()) { - db.close(); - } - - if (dbFile.exists()) { - boolean delete = dbFile.delete(); - assertTrue(delete); - } - } - - @Test(expected = ValidationException.class) - public void testSerializabilityValidation() { - for (int i = 0; i < 5; i++) { - Document doc = Document.createDocument(); - doc.put("key", i); - doc.put("data", new NotSerializableClass(Integer.toString(i))); - collection.insert(doc); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("Write " + i + " completed"); - } - } - - @Test - public void testSerializablity() { - for (int i = 0; i < 5; i++) { - Document doc = Document.createDocument(); - doc.put("key", i); - doc.put("data", new SerializableClass(Integer.toString(i))); - collection.insert(doc); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("Write " + i + " completed"); - } - } - - @Data - public static class NotSerializableClass { - private String myId; - - public NotSerializableClass(String myId) { - this.myId = myId; - } - } - - @Data - public static class SerializableClass implements Serializable { - private String myId; - - public SerializableClass(String myId) { - this.myId = myId; - } - } -} - - diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/StressTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/StressTest.java deleted file mode 100644 index e4b12abf4..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/StressTest.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.mvstore.MVStoreModule; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import uk.co.jemos.podam.api.PodamFactory; -import uk.co.jemos.podam.api.PodamFactoryImpl; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import java.util.concurrent.atomic.AtomicLong; - -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee - */ -public class StressTest { - private final String fileName = getRandomTempDbFile(); - private Nitrite db; - private NitriteCollection collection; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void before() { - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(fileName) - .compress(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(); - - collection = db.getCollection("test"); - System.out.println(fileName); - } - - @Test - public void testIssue41() { - collection.createIndex("number", IndexOptions.indexOptions(IndexType.NonUnique)); - collection.createIndex("name", IndexOptions.indexOptions(IndexType.NonUnique)); - collection.createIndex("counter", IndexOptions.indexOptions(IndexType.Unique)); - - Random random = new Random(); - AtomicLong counter = new AtomicLong(System.currentTimeMillis()); - PodamFactory factory = new PodamFactoryImpl(); - - long start = System.currentTimeMillis(); - for (int i = 0; i < 100000; i++) { - Document doc = Document.createDocument(); - doc.put("number", random.nextDouble()); - doc.put("name", factory.manufacturePojo(String.class)); - doc.put("counter", counter.getAndIncrement()); - collection.insert(doc); - if (i % 10000 == 0) { - System.out.println(i + " entries written"); - } - } - System.out.println("Records inserted in " + ((System.currentTimeMillis() - start) / (1000 * 60)) + " minutes"); - - if (db.hasUnsavedChanges()) { - db.commit(); - } - - start = System.currentTimeMillis(); - DocumentCursor cursor = collection.find(); - System.out.println("Size ->" + cursor.size()); - System.out.println("Records size calculated in " + ((System.currentTimeMillis() - start) / (1000)) + " seconds"); - - int i = 0; - start = System.currentTimeMillis(); - for (Document element : cursor) { - assertNotNull(element); - i++; - if (i % 10000 == 0) { - System.out.println(i + " entries processed"); - } - } - System.out.println("Iteration completed in " + ((System.currentTimeMillis() - start) / (1000)) + " seconds"); - } - - @After - public void clear() throws IOException { - if (db != null && !db.isClosed()) { - long start = System.currentTimeMillis(); - db.close(); - System.out.println("Time to compact and close - " + (System.currentTimeMillis() - start) / 1000 + " seconds"); - } - Files.delete(Paths.get(fileName)); - } - - @Test - public void testRepoPerformanceWithIndex() { - // warm-up - List items = getItems(PerfTestIndexed.class); - ObjectRepository repo = db.getRepository(PerfTestIndexed.class); - for (PerfTestIndexed item : items) { - assertNotNull(item); - repo.insert(item); - } - repo.remove(Filter.ALL); - repo.drop(); - - // actual calculation - repo = db.getRepository(PerfTestIndexed.class); - long start = System.currentTimeMillis(); - for (PerfTestIndexed item : items) { - repo.insert(item); - } - long diff = System.currentTimeMillis() - start; - System.out.println("Time take to insert 10000 indexed items - " + diff + "ms"); - - start = System.currentTimeMillis(); - repo.remove(Filter.ALL); - diff = System.currentTimeMillis() - start; - System.out.println("Time take to remove 10000 indexed items - " + diff + "ms"); - } - - @Test - public void testRepoPerformanceWithoutIndex() { - // warm-up - List items = getItems(PerfTest.class); - ObjectRepository repo = db.getRepository(PerfTest.class); - for (PerfTest item : items) { - assertNotNull(item); - repo.insert(item); - } - repo.remove(Filter.ALL); - repo.drop(); - - // actual calculation - repo = db.getRepository(PerfTest.class); - long start = System.currentTimeMillis(); - for (PerfTest item : items) { - repo.insert(item); - } - long diff = System.currentTimeMillis() - start; - System.out.println("Time take to insert 10000 non-indexed items - " + diff + "ms"); - - start = System.currentTimeMillis(); - repo.remove(Filter.ALL); - diff = System.currentTimeMillis() - start; - System.out.println("Time take to remove 10000 non-indexed items - " + diff + "ms"); - } - - private List getItems(Class type) { - PodamFactory generator = new PodamFactoryImpl(); - List items = new ArrayList<>(); - for (int i = 0; i < 10000; i++) { - items.add(generator.manufacturePojoWithFullData(type)); - } - assertEquals(items.size(), 10000); - return items; - } - - @Data - public static class PerfTest implements Mappable { - private String firstName; - private String lastName; - private Integer age; - private String text; - - @Override - public Document write(NitriteMapper mapper) { - Document document = Document.createDocument(); - document.put("firstName", firstName); - document.put("lastName", lastName); - document.put("age", age); - document.put("text", text); - return document; - } - - @Override - public void read(NitriteMapper mapper, Document document) { - this.firstName = (String) document.get("firstName"); - this.lastName = (String) document.get("lastName"); - this.age = (Integer) document.get("age"); - this.text = (String) document.get("text"); - } - } - - @Indices({ - @Index(value = "firstName", type = IndexType.NonUnique), - @Index(value = "age", type = IndexType.NonUnique), - @Index(value = "text", type = IndexType.Fulltext), - }) - private static class PerfTestIndexed extends PerfTest { - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/TestUtil.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/TestUtil.java deleted file mode 100644 index d95b25961..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/TestUtil.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (c) 2019-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.extern.slf4j.Slf4j; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.exceptions.ObjectMappingException; -import org.dizitart.no2.mvstore.MVStoreModule; - -import java.io.IOException; -import java.util.*; - -/** - * @author Anindya Chatterjee - */ -@Slf4j -public class TestUtil { - - /** - * Determines whether the supplied `iterable` is sorted. - * - * @param the type parameter - * @param iterable the iterable - * @param ascending a boolean value indicating whether to sort in ascending order - * @return the boolean value indicating if `iterable` is sorted or not. - */ - public static > boolean isSorted(Iterable iterable, boolean ascending) { - Iterator iterator = iterable.iterator(); - if (!iterator.hasNext()) { - return true; - } - T t = iterator.next(); - while (iterator.hasNext()) { - T t2 = iterator.next(); - if (ascending) { - if (t.compareTo(t2) > 0) { - return false; - } - } else { - if (t.compareTo(t2) < 0) { - return false; - } - } - t = t2; - } - return true; - } - - public static Nitrite createDb() { - MVStoreModule storeModule = MVStoreModule.withConfig() - .build(); - - return Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(); - } - - public static Nitrite createDb(String user, String password) { - MVStoreModule storeModule = MVStoreModule.withConfig() - .build(); - - return Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(user, password); - } - - public static Nitrite createDb(String filePath) { - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(filePath) - .compress(true) - .build(); - - return Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(); - } - - public static Nitrite createDb(String filePath, String user, String password) { - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(filePath) - .compress(true) - .build(); - - return Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(user, password); - } - - public static Document parse(String json) { - try { - ObjectMapper objectMapper = createObjectMapper(); - JsonNode node = objectMapper.readValue(json, JsonNode.class); - return loadDocument(node); - } catch (IOException e) { - log.error("Error while parsing json", e); - throw new ObjectMappingException("failed to parse json " + json); - } - } - - private static Document loadDocument(JsonNode node) { - Map objectMap = new LinkedHashMap<>(); - Iterator> fields = node.fields(); - while (fields.hasNext()) { - Map.Entry entry = fields.next(); - String name = entry.getKey(); - JsonNode value = entry.getValue(); - Object object = loadObject(value); - objectMap.put(name, object); - } - - return Document.createDocument(objectMap); - } - - private static Object loadObject(JsonNode node) { - if (node == null) - return null; - try { - switch (node.getNodeType()) { - case ARRAY: - return loadArray(node); - case BINARY: - return node.binaryValue(); - case BOOLEAN: - return node.booleanValue(); - case MISSING: - case NULL: - return null; - case NUMBER: - return node.numberValue(); - case OBJECT: - case POJO: - return loadDocument(node); - case STRING: - return node.textValue(); - } - } catch (IOException e) { - return null; - } - return null; - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - private static List loadArray(JsonNode array) { - if (array.isArray()) { - List list = new ArrayList(); - Iterator iterator = array.elements(); - while (iterator.hasNext()) { - Object element = iterator.next(); - if (element instanceof JsonNode) { - list.add(loadObject((JsonNode) element)); - } else { - list.add(element); - } - } - return list; - } - return null; - } - - - private static ObjectMapper createObjectMapper() { - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.setVisibility( - objectMapper.getSerializationConfig().getDefaultVisibilityChecker() - .withFieldVisibility(JsonAutoDetect.Visibility.ANY) - .withGetterVisibility(JsonAutoDetect.Visibility.NONE) - .withIsGetterVisibility(JsonAutoDetect.Visibility.NONE)); - objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); - objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); - objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true); - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - - objectMapper.findAndRegisterModules(); - return objectMapper; - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/BaseCollectionTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/BaseCollectionTest.java deleted file mode 100644 index 8b59d4a1c..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/BaseCollectionTest.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import lombok.extern.slf4j.Slf4j; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.Retry; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.mvstore.MVStoreModule; -import org.dizitart.no2.mvstore.MVStoreModuleBuilder; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.nio.file.Files; -import java.nio.file.Paths; -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Collection; -import java.util.Locale; - -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.Filter.ALL; - -@Slf4j -@RunWith(value = Parameterized.class) -public abstract class BaseCollectionTest { - @Parameterized.Parameter - public boolean inMemory = false; - @Parameterized.Parameter(value = 1) - public boolean isSecured = false; - @Parameterized.Parameter(value = 2) - public boolean isCompressed = false; - @Parameterized.Parameter(value = 3) - public boolean isAutoCommit = false; - - protected Nitrite db; - protected NitriteCollection collection; - protected Document doc1, doc2, doc3; - protected SimpleDateFormat simpleDateFormat; - private final String fileName = getRandomTempDbFile(); - - @Rule - public Retry retry = new Retry(3); - - @Parameterized.Parameters(name = "InMemory = {0}, Secured = {1}, " + - "Compressed = {2}, AutoCommit = {3}, AutoCompact = {4}") - public static Collection data() { - return Arrays.asList(new Object[][]{ - {false, false, false, false}, - {false, false, false, true}, - {false, false, true, false}, - {false, false, true, true}, - {false, true, false, false}, - {false, true, false, true}, - {false, true, true, false}, - {false, true, true, true}, - {true, false, false, false}, - {true, false, false, true}, - {true, false, true, false}, - {true, false, true, true}, - {true, true, false, false}, - {true, true, false, true}, - {true, true, true, false}, - {true, true, true, true}, - }); - } - - @Before - public void setUp() { - try { - openDb(); - - simpleDateFormat - = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); - - doc1 = createDocument("firstName", "fn1") - .put("lastName", "ln1") - .put("birthDay", simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) - .put("data", new byte[]{1, 2, 3}) - .put("list", Arrays.asList("one", "two", "three")) - .put("body", "a quick brown fox jump over the lazy dog"); - doc2 = createDocument("firstName", "fn2") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2010-06-12T16:02:48.440Z")) - .put("data", new byte[]{3, 4, 3}) - .put("list", Arrays.asList("three", "four", "three")) - .put("body", "quick hello world from nitrite"); - doc3 = createDocument("firstName", "fn3") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2014-04-17T16:02:48.440Z")) - .put("data", new byte[]{9, 4, 8}) - .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + - "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); - - collection = db.getCollection("test"); - collection.remove(ALL); - } catch (Throwable t) { - log.error("Error while initializing test database", t); - } - } - - @After - public void clear() { - try { - if (collection != null && !collection.isDropped()) { - collection.close(); - } - if (db != null && !db.isClosed()) db.close(); - if (!inMemory) { - Files.delete(Paths.get(fileName)); - } - } catch (Throwable t) { - log.error("Error while clearing test database", t); - } - } - - private void openDb() { - MVStoreModuleBuilder builder = MVStoreModule.withConfig(); - - if (isCompressed) { - builder.compress(true); - } - - if (!isAutoCommit) { - builder.autoCommit(false); - } - - if (!inMemory) { - builder.filePath(fileName); - } - - MVStoreModule storeModule = builder.build(); - NitriteBuilder nitriteBuilder = Nitrite.builder() - .fieldSeparator(".") - .loadModule(storeModule); - - if (isSecured) { - db = nitriteBuilder.openOrCreate("test-user", "test-password"); - } else { - db = nitriteBuilder.openOrCreate(); - } - } - - protected WriteResult insert() { - return collection.insert(doc1, doc2, doc3); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionDeleteNegativeTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionDeleteNegativeTest.java deleted file mode 100644 index 61ac96fc5..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionDeleteNegativeTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.ValidationException; -import org.junit.Test; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionDeleteNegativeTest extends BaseCollectionTest { - @Test(expected = NitriteIOException.class) - public void testDrop() { - collection.drop(); - insert(); - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - } - - @Test(expected = FilterException.class) - public void testDeleteWithInvalidFilter() { - insert(); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - - WriteResult writeResult = collection.remove(where("lastName").gt(null)); - assertEquals(writeResult.getAffectedCount(), 0); - } - - @Test(expected = ValidationException.class) - public void testDeleteNullDocument() { - insert(); - - collection.remove((Document) null); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionDeleteTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionDeleteTest.java deleted file mode 100644 index 32a513827..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionDeleteTest.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.junit.Test; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -public class CollectionDeleteTest extends BaseCollectionTest { - - @Test - public void testDelete() { - insert(); - - WriteResult writeResult = collection.remove(where("lastName").notEq(null)); - assertEquals(writeResult.getAffectedCount(), 3); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 0); - } - - @Test - public void testDeleteWithOptions() { - insert(); - - WriteResult writeResult = collection.remove(where("lastName").notEq(null), true); - assertEquals(writeResult.getAffectedCount(), 1); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 2); - } - - @Test - public void testDeleteWithNonMatchingFilter() { - insert(); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - - WriteResult writeResult = collection.remove(where("lastName").eq("a")); - assertEquals(writeResult.getAffectedCount(), 0); - } - - @Test - public void testDeleteInEmptyCollection() { - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 0); - - WriteResult writeResult = collection.remove(where("lastName").notEq(null)); - assertEquals(writeResult.getAffectedCount(), 0); - } - - @Test - public void testClear() { - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.Unique)); - insert(); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - assertTrue(collection.hasIndex("firstName")); - - boolean uniqueError = false; - try { - collection.insert(doc1); - } catch (Exception e) { - uniqueError = true; - } finally { - assertTrue(uniqueError); - } - - collection.remove(Filter.ALL); - - cursor = collection.find(); - assertEquals(cursor.size(), 0); - assertTrue(collection.hasIndex("firstName")); - - collection.insert(doc1); - cursor = collection.find(); - assertEquals(cursor.size(), 1); - assertTrue(collection.hasIndex("firstName")); - } - - @Test - public void testRemoveAll() { - insert(); - WriteResult writeResult = collection.remove((Filter) null); - assertEquals(writeResult.getAffectedCount(), 3); - } - - @Test - public void testRemoveDocument() { - insert(); - - WriteResult writeResult = collection.remove(where("firstName").eq("fn1")); - assertEquals(writeResult.getAffectedCount(), 1); - assertEquals(collection.size(), 2); - - writeResult = collection.remove(where("firstName").eq("fn2")); - assertEquals(writeResult.getAffectedCount(), 1); - assertEquals(collection.size(), 1); - - assertEquals(collection.find(where("firstName").eq("fn1")).size(), 0); - assertEquals(collection.find(where("firstName").eq("fn2")).size(), 0); - assertEquals(collection.find(where("firstName").eq("fn3")).size(), 1); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionFactoryTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionFactoryTest.java deleted file mode 100644 index 47677200a..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionFactoryTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.NitriteConfig; -import org.dizitart.no2.Retry; -import org.dizitart.no2.common.concurrent.LockService; -import org.dizitart.no2.exceptions.ValidationException; -import org.junit.Rule; -import org.junit.Test; - -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee - */ -public class CollectionFactoryTest { - - @Rule - public Retry retry = new Retry(3); - - @Test(expected = ValidationException.class) - public void testGetCollectionMapStoreNull() { - CollectionFactory factory = new CollectionFactory(new LockService()); - assertNotNull(factory); - - NitriteConfig config = new NitriteConfig(); - factory.getCollection(null, config, true); - } - - @Test(expected = ValidationException.class) - public void testGetCollectionContextNull() { - CollectionFactory factory = new CollectionFactory(new LockService()); - factory.getCollection("test", null, false); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionFindByIndexNegativeTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionFindByIndexNegativeTest.java deleted file mode 100644 index feb80b76b..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionFindByIndexNegativeTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.junit.Test; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionFindByIndexNegativeTest extends BaseCollectionTest { - @Test(expected = FilterException.class) - public void testFindTextWithWildCardMultipleWord() { - insert(); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - - DocumentCursor cursor = collection.find(where("body").text("*ipsum dolor*")); - assertEquals(cursor.size(), 1); - } - - @Test(expected = FilterException.class) - public void testFindTextWithOnlyWildCard() { - insert(); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - - DocumentCursor cursor = collection.find(where("body").text("*")); - assertEquals(cursor.size(), 1); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionFindByIndexTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionFindByIndexTest.java deleted file mode 100644 index ab1df95a3..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionFindByIndexTest.java +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import com.github.javafaker.Faker; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.junit.Test; - -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; - -import static org.dizitart.no2.TestUtil.isSorted; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionFindByIndexTest extends BaseCollectionTest { - - @Test - public void testFindByUniqueIndex() throws ParseException { - insert(); - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.Unique)); - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("firstName").eq("fn10")); - assertEquals(cursor.size(), 0); - - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.Unique)); - cursor = collection.find(where("birthDay").gt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").gte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lte( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").lt( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").gt( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").gte( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .and(where("firstName").eq("fn1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12"))); - assertEquals(cursor.size(), 3); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1")).not()); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").eq((byte) 4)); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").lt(4)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("firstName").notIn("fn1", "fn2")); - assertEquals(cursor.size(), 1); - } - - @Test - public void testFindByNonUniqueIndex() throws ParseException { - insert(); - collection.createIndex("lastName", IndexOptions.indexOptions(IndexType.NonUnique)); - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.NonUnique)); - - DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("lastName").eq("ln20")); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").gt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").gte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lte( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").lt( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").gt( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").gte( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .and(where("firstName").eq("fn1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12"))); - assertEquals(cursor.size(), 3); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1")).not()); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").eq((byte) 4)); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").lt(4)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("firstName").notIn("fn1", "fn2")); - assertEquals(cursor.size(), 1); - } - - @Test - public void testFindByFullTextIndexAfterInsert() { - insert(); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("body")); - - DocumentCursor cursor = collection.find(where("body").text("Lorem")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("body").text("nosql")); - assertEquals(cursor.size(), 0); - - collection.dropIndex("body"); - boolean filterException = false; - try { - collection.find(where("body").text("Lorem")).toList(); - } catch (FilterException fe) { - filterException = true; - } finally { - assertTrue(filterException); - } - } - - @Test - public void testFindByFullTextIndexBeforeInsert() { - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("body")); - insert(); - - DocumentCursor cursor = collection.find(where("body").text("Lorem")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("body").text("quick brown")); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("body").text("nosql")); - assertEquals(cursor.size(), 0); - - collection.dropIndex("body"); - boolean filterException = false; - try { - collection.find(where("body").text("Lorem")).toList(); - } catch (FilterException fe) { - filterException = true; - } finally { - assertTrue(filterException); - } - } - - @Test - public void testFindByIndexSortAscending() { - insert(); - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.Unique)); - - DocumentCursor cursor = collection.find().sort("birthDay", SortOrder.Ascending); - assertEquals(cursor.size(), 3); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, true)); - } - - @Test - public void testFindByIndexSortDescending() { - insert(); - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.Unique)); - - DocumentCursor cursor = collection.find().sort("birthDay", SortOrder.Descending); - assertEquals(cursor.size(), 3); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, false)); - } - - @Test - public void testFindByIndexLimitAndSort() { - insert(); - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.Unique)); - - DocumentCursor cursor = collection.find(). - sort("birthDay", SortOrder.Descending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, false)); - - cursor = collection.find(). - sort("birthDay", SortOrder.Ascending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, true)); - - cursor = collection.find(). - sort("firstName", SortOrder.Ascending).skipLimit(0, 30); - assertEquals(cursor.size(), 3); - List nameList = new ArrayList<>(); - for (Document document : cursor) { - nameList.add(document.get("firstName", String.class)); - } - assertTrue(isSorted(nameList, true)); - } - - @Test - public void testFindAfterDroppedIndex() { - insert(); - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.Unique)); - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - - collection.dropIndex("firstName"); - cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - } - - @Test - public void testFindTextWithWildCard() { - insert(); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - - DocumentCursor cursor = collection.find(where("body").text("Lo")); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("body").text("Lo*")); - assertEquals(cursor.size(), 1); // Lorem - - cursor = collection.find(where("body").text("*rem")); - assertEquals(cursor.size(), 1); // lorem - - cursor = collection.find(where("body").text("*or*")); - assertEquals(cursor.size(), 2); - } - - @Test - public void testFindTextWithEmptyString() { - insert(); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - - DocumentCursor cursor = collection.find(where("body").text("")); - assertEquals(cursor.size(), 0); - } - - @Test - public void testFindWithOrIndexed() { - NitriteCollection collection = db.getCollection("testFindWithOrIndexed"); - Document doc1 = Document.createDocument("firstName", "John").put("lastName", "Doe"); - Document doc2 = Document.createDocument("firstName", "Jane").put("lastName", "Doe"); - Document doc3 = Document.createDocument("firstName", "Jonas").put("lastName", "Doe"); - Document doc4 = Document.createDocument("firstName", "Johan").put("lastName", "Day"); - - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.Unique)); - collection.createIndex("lastName", IndexOptions.indexOptions(IndexType.NonUnique)); - - collection.insert(doc1, doc2, doc3, doc4); - - DocumentCursor cursor = collection.find(where("firstName").eq("John").or(where("lastName").eq("Day"))); - assertEquals(cursor.size(), 2); - - List list = cursor.toList(); - assertEquals(list.size(), 2); - } - - @Test - public void testIssue45() { - NitriteCollection collection = db.getCollection("testIssue45"); - Faker faker = new Faker(); - String text1 = faker.lorem().paragraph() + " quick brown"; - String text2 = faker.lorem().paragraph() + " fox jump"; - String text3 = faker.lorem().paragraph() + " over lazy"; - String text4 = faker.lorem().paragraph() + " dog"; - - List list1 = Arrays.asList(text1, text2); - List list2 = Arrays.asList(text1, text2, text3); - List list3 = Arrays.asList(text2, text3); - List list4 = Arrays.asList(text1, text2, text3, text4); - - Document doc1 = Document.createDocument("firstName", "John").put("notes", list1); - Document doc2 = Document.createDocument("firstName", "Jane").put("notes", list2); - Document doc3 = Document.createDocument("firstName", "Jonas").put("notes", list3); - Document doc4 = Document.createDocument("firstName", "Johan").put("notes", list4); - - collection.createIndex("notes", IndexOptions.indexOptions(IndexType.Fulltext)); - collection.insert(doc1, doc2, doc3, doc4); - - DocumentCursor cursor = collection.find(where("notes").text("fox")); - assertEquals(cursor.size(), 4); - - cursor = collection.find(where("notes").text("dog")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("notes").text("lazy")); - assertEquals(cursor.size(), 3); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionFindNegativeTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionFindNegativeTest.java deleted file mode 100644 index cf85610fe..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionFindNegativeTest.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.exceptions.ValidationException; -import org.junit.Test; - -import java.util.Date; -import java.util.List; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionFindNegativeTest extends BaseCollectionTest { - @Test(expected = ValidationException.class) - public void testFindFilterInvalidIndex() { - insert(); - collection.find(where("data.9").eq(4)).toList(); - } - - @Test(expected = ValidationException.class) - public void testFindOptionsNegativeOffset() { - insert(); - collection.find().skipLimit(-1, 1); - } - - @Test(expected = ValidationException.class) - public void testFindOptionsNegativeSize() { - insert(); - collection.find().skipLimit(0, -1); - } - - public void testFindOptionsInvalidOffset() { - insert(); - assertEquals(collection.find().skipLimit(10, 1).size(), 0); - } - - @Test(expected = ValidationException.class) - public void testFindInvalidSort() { - insert(); - collection.find().sort("data", SortOrder.Descending).toList(); - } - - @Test(expected = FilterException.class) - public void testFindTextFilterNonIndexed() { - insert(); - collection.find(where("body").text("Lorem")).toList(); - } - - @Test(expected = FilterException.class) - public void testFindWithRegexInvalidValue() { - insert(); - DocumentCursor cursor = collection.find(where("birthDay").regex("hello")); - assertEquals(cursor.size(), 1); - } - - @Test(expected = ValidationException.class) - public void testInvalidProjection() { - insert(); - DocumentCursor cursor = collection.find(where("birthDay").lte(new Date())). - sort("firstName", SortOrder.Ascending).skipLimit(0, 3); - - Document projection = createDocument("firstName", null) - .put("lastName", "ln2"); - - cursor.project(projection); - } - - @Test(expected = UnsupportedOperationException.class) - public void testToListAdd() { - insert(); - DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); - List documents = cursor.toList(); - documents.add(createDocument()); - } - - @Test(expected = UnsupportedOperationException.class) - public void testToListRemove() { - insert(); - DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); - List documents = cursor.toList(); - documents.clear(); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionFindTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionFindTest.java deleted file mode 100644 index d5bc4faca..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionFindTest.java +++ /dev/null @@ -1,856 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.common.NullOrder; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.exceptions.IndexingException; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.joda.time.DateTime; -import org.junit.Test; - -import java.text.Collator; -import java.text.ParseException; -import java.util.*; -import java.util.stream.Collectors; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.common.Constants.*; -import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; -import static org.dizitart.no2.TestUtil.isSorted; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.$; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.*; -import static org.hamcrest.MatcherAssert.assertThat; - -public class CollectionFindTest extends BaseCollectionTest { - - private static Document trimMeta(Document document) { - document.remove(DOC_ID); - document.remove(DOC_REVISION); - document.remove(DOC_MODIFIED); - document.remove(DOC_SOURCE); - return document; - } - - @Test - public void testFindAll() { - insert(); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - } - - @Test - public void testFindWithFilter() throws ParseException { - insert(); - - DocumentCursor cursor = collection.find(where("birthDay").gt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").gte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lte( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").lt( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").gt( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").gte( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .and(where("firstName").eq("fn1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12"))); - assertEquals(cursor.size(), 3); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1")).not()); - assertEquals(cursor.size(), 2); - - - cursor = collection.find(where("data.1").eq((byte) 4)); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").lt(4)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("firstName").notIn("fn1", "fn2")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(ALL.not()); - assertEquals(cursor.size(), 0); - } - - @Test - public void testFindWithSkipLimit() { - insert(); - - DocumentCursor cursor = collection.find().skipLimit(0, 1); - assertEquals(cursor.size(), 1); - - cursor = collection.find().skipLimit(1, 3); - assertEquals(cursor.size(), 2); - - cursor = collection.find().skipLimit(0, 30); - assertEquals(cursor.size(), 3); - - cursor = collection.find().skipLimit(2, 3); - assertEquals(cursor.size(), 1); - } - - @Test - public void testFindWithSkip() { - insert(); - - DocumentCursor cursor = collection.find().skip(0); - assertEquals(cursor.size(), 3); - - cursor = collection.find().skip(1); - assertEquals(cursor.size(), 2); - - cursor = collection.find().skip(30); - assertEquals(cursor.size(), 0); - - cursor = collection.find().skip(2); - assertEquals(cursor.size(), 1); - - boolean invalid = false; - try { - cursor = collection.find().skip(-1); - assertEquals(cursor.size(), 1); - } catch (ValidationException e) { - invalid = true; - } - assertTrue(invalid); - } - - @Test - public void testFindWithLimit() { - insert(); - - DocumentCursor cursor = collection.find().limit(0); - assertEquals(cursor.size(), 0); - - cursor = collection.find().limit(1); - assertEquals(cursor.size(), 1); - - boolean invalid = false; - try { - cursor = collection.find().limit(-1); - assertEquals(cursor.size(), 1); - } catch (ValidationException e) { - invalid = true; - } - assertTrue(invalid); - - cursor = collection.find().limit(30); - assertEquals(cursor.size(), 3); - } - - @Test - public void testFindSortAscending() { - insert(); - - DocumentCursor cursor = collection.find().sort("birthDay", SortOrder.Ascending); - assertEquals(cursor.size(), 3); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, true)); - } - - @Test - public void testFindSortDescending() { - insert(); - - DocumentCursor cursor = collection.find().sort("birthDay", SortOrder.Descending); - assertEquals(cursor.size(), 3); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, false)); - } - - @Test - public void testFindLimitAndSort() { - insert(); - - DocumentCursor cursor = collection.find(). - sort("birthDay", SortOrder.Descending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, false)); - - cursor = collection.find(). - sort("birthDay", SortOrder.Ascending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, true)); - - cursor = collection.find(). - sort("firstName", SortOrder.Ascending).skipLimit(0, 30); - assertEquals(cursor.size(), 3); - List nameList = new ArrayList<>(); - for (Document document : cursor) { - nameList.add(document.get("firstName", String.class)); - } - assertTrue(isSorted(nameList, true)); - } - - @Test - public void testFindSortOnNonExistingField() { - insert(); - DocumentCursor cursor = collection.find().sort("my-value", SortOrder.Descending); - assertEquals(cursor.size(), 3); - } - - @Test - public void testFindInvalidField() { - insert(); - DocumentCursor cursor = collection.find(where("myField").eq("myData")); - assertEquals(cursor.size(), 0); - } - - @Test - public void testFindInvalidFieldWithInvalidAccessor() { - insert(); - DocumentCursor cursor = collection.find(where("myField.0").eq("myData")); - assertEquals(cursor.size(), 0); - } - - @Test - public void testFindLimitAndSortInvalidField() { - insert(); - DocumentCursor cursor = collection.find(). - sort("birthDay2", SortOrder.Descending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - } - - @Test - public void testGetById() { - collection.insert(doc1); - NitriteId id = NitriteId.createId("1"); - Document document = collection.getById(id); - assertNull(document); - - document = collection.find().firstOrNull(); - - assertEquals(document.get(DOC_ID), document.getId().getIdValue()); - assertEquals(document.get("firstName"), "fn1"); - assertEquals(document.get("lastName"), "ln1"); - assertArrayEquals((byte[]) document.get("data"), new byte[]{1, 2, 3}); - assertEquals(document.get("body"), "a quick brown fox jump over the lazy dog"); - } - - @Test - public void testFindWithFilterAndOption() { - insert(); - DocumentCursor cursor = collection.find(where("birthDay").lte(new Date())). - sort("firstName", SortOrder.Ascending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - } - - @Test - public void testFindTextWithRegex() { - insert(); - DocumentCursor cursor = collection.find(where("body").regex("hello")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("body").regex("test")); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("body").regex("^hello$")); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("body").regex(".*")); - assertEquals(cursor.size(), 3); - } - - @Test - public void testProject() { - insert(); - DocumentCursor cursor = collection.find(where("birthDay").lte(new Date())). - sort("firstName", SortOrder.Ascending).skipLimit(0, 3); - int iteration = 0; - for (Document document : cursor) { - switch (iteration) { - case 0: - assertTrue(isSimilar(document, doc1, "firstName", "lastName", "birthDay", "data", "list", "body")); - break; - case 1: - assertTrue(isSimilar(document, doc2, "firstName", "lastName", "birthDay", "data", "list", "body")); - break; - case 2: - assertTrue(isSimilar(document, doc3, "firstName", "lastName", "birthDay", "data", "list", "body")); - break; - } - iteration++; - } - assertEquals(iteration, 3); - } - - @Test - public void testProjectWithCustomDocument() { - insert(); - DocumentCursor cursor = collection.find(where("birthDay").lte(new Date())). - sort("firstName", SortOrder.Ascending).skipLimit(0, 3); - - Document projection = createDocument("firstName", null) - .put("lastName", null); - - Iterable documents = cursor.project(projection); - int iteration = 0; - for (Document document : documents) { - assertTrue(document.containsKey("firstName")); - assertTrue(document.containsKey("lastName")); - - assertFalse(document.containsKey("_id")); - assertFalse(document.containsKey("birthDay")); - assertFalse(document.containsKey("data")); - assertFalse(document.containsKey("body")); - - switch (iteration) { - case 0: - assertEquals(document.get("firstName"), "fn1"); - assertEquals(document.get("lastName"), "ln1"); - break; - case 1: - assertEquals(document.get("firstName"), "fn2"); - assertEquals(document.get("lastName"), "ln2"); - break; - case 2: - assertEquals(document.get("firstName"), "fn3"); - assertEquals(document.get("lastName"), "ln2"); - break; - } - iteration++; - } - assertEquals(iteration, 3); - } - - @Test - public void testFindWithArrayEqual() { - insert(); - DocumentCursor ids = collection.find(where("data").eq(new byte[]{3, 4, 3})); - assertNotNull(ids); - assertEquals(ids.size(), 1); - } - - @Test - public void testFindWithArrayEqualFailForWrongCardinality() { - insert(); - DocumentCursor ids = collection.find(where("data").eq(new byte[]{4, 3, 3})); - assertNotNull(ids); - assertEquals(ids.size(), 0); - } - - @Test - public void testFindWithIterableEqual() { - insert(); - DocumentCursor ids = collection.find(where("list").eq( - new ArrayList() {{ - add("three"); - add("four"); - add("three"); - }})); - assertNotNull(ids); - assertEquals(ids.size(), 1); - } - - @Test - public void testFindWithIterableEqualFailForWrongCardinality() { - insert(); - DocumentCursor ids = collection.find(where("list").eq( - new ArrayList() {{ - add("four"); - add("three"); - add("three"); - }})); - assertNotNull(ids); - assertEquals(ids.size(), 0); - } - - @Test - public void testFindInArray() { - insert(); - DocumentCursor ids = collection.find(where("data").elemMatch($.gte(2).and($.lt(5)))); - assertNotNull(ids); - assertEquals(ids.size(), 3); - - ids = collection.find(where("data").elemMatch($.gt(2).or($.lte(5)))); - assertNotNull(ids); - assertEquals(ids.size(), 3); - - ids = collection.find(where("data").elemMatch($.gt(1).and($.lt(4)))); - assertNotNull(ids); - assertEquals(ids.size(), 2); - } - - @Test - public void testFindInList() { - insert(); - DocumentCursor ids = collection.find(where("list").elemMatch($.regex("three"))); - assertNotNull(ids); - assertEquals(ids.size(), 2); - - ids = collection.find(where("list").elemMatch($.regex("hello"))); - assertNotNull(ids); - assertEquals(ids.size(), 0); - - ids = collection.find(where("list").elemMatch($.regex("hello").not())); - assertNotNull(ids); - assertEquals(ids.size(), 2); - } - - @Test - public void testElemMatchFilter() { - Document doc1 = createDocument("productScores", new Document[]{ - createDocument("product", "abc").put("score", 10), - createDocument("product", "xyz").put("score", 5) - }).put("strArray", new String[]{"a", "b"}); - - Document doc2 = createDocument("productScores", new Document[]{ - createDocument("product", "abc").put("score", 8), - createDocument("product", "xyz").put("score", 7) - }).put("strArray", new String[]{"d", "e"}); - - Document doc3 = createDocument("productScores", new Document[]{ - createDocument("product", "abc").put("score", 7), - createDocument("product", "xyz").put("score", 8) - }).put("strArray", new String[]{"a", "f"}); - - NitriteCollection prodCollection = db.getCollection("prodScore"); - prodCollection.insert(doc1, doc2, doc3); - - List documentList = prodCollection.find(where("productScores") - .elemMatch(where("product").eq("xyz").and(where("score").gte(8)))).toList(); - - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").lte(8).not())).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("product").eq("xyz").or(where("score").gte(8)))).toList(); - assertEquals(documentList.size(), 3); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("product").eq("xyz"))).toList(); - assertEquals(documentList.size(), 3); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").gte(10))).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").gt(8))).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").lt(7))).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").lte(7))).toList(); - assertEquals(documentList.size(), 3); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").in(7, 8))).toList(); - assertEquals(documentList.size(), 2); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").notIn(7, 8))).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("product").regex("xyz"))).toList(); - assertEquals(documentList.size(), 3); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.eq("a"))).toList(); - assertEquals(documentList.size(), 2); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.eq("a").or($.eq("f").or($.eq("b"))).not())).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.gt("e"))).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.gte("e"))).toList(); - assertEquals(documentList.size(), 2); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.lte("b"))).toList(); - assertEquals(documentList.size(), 2); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.lt("a"))).toList(); - assertEquals(documentList.size(), 0); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.in("a", "f"))).toList(); - assertEquals(documentList.size(), 2); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.regex("a"))).toList(); - assertEquals(documentList.size(), 2); - - } - - @Test - public void testNotEqualFilter() { - Document document = createDocument("abc", "123"); - document.put("xyz", null); - - collection.insert(document); - DocumentCursor cursor = collection.find(where("abc").eq("123")); - assertEquals(cursor.size(), 1); - assertEquals(cursor.toList().size(), 1); - - cursor = collection.find(where("xyz").eq(null)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("abc").notEq(null)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("abc").notEq(null).and(where("xyz").eq(null))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("abc").eq(null).and(where("xyz").notEq(null))); - assertEquals(cursor.size(), 0); - - collection.remove(ALL); - - document = createDocument("field", "two"); - document.put(DOC_REVISION, 1482225343161L); - - collection.insert(document); - Document projection = collection.find( - where(DOC_REVISION).gte(1482225343160L) - .and(where(DOC_REVISION).lte(1482225343162L) - .and(where(DOC_REVISION).notEq(null)))) - .firstOrNull(); - - assertNull(projection); - } - - @Test - public void testFilterAll() { - DocumentCursor cursor = collection.find(ALL); - assertNotNull(cursor); - assertEquals(cursor.size(), 0); - - insert(); - cursor = collection.find(ALL); - assertNotNull(cursor); - assertEquals(cursor.size(), 3); - } - - @Test - public void testIssue72() { - NitriteCollection coll = db.getCollection("test"); - coll.createIndex("id", IndexOptions.indexOptions(IndexType.Unique)); - coll.createIndex("group", IndexOptions.indexOptions(IndexType.NonUnique)); - - coll.remove(ALL); - - Document doc = createDocument().put("id", "test-1").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - doc = createDocument().put("id", "test-2").put("group", "groupA").put("startTime", DateTime.now()); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - DocumentCursor cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending); - assertEquals(2, cursor.size()); - assertNull(cursor.toList().get(1).get("startTime")); - assertNotNull(cursor.toList().get(0).get("startTime")); - - cursor = coll.find(where("group").eq("groupA")).sort("startTime", SortOrder.Ascending); - assertEquals(2, cursor.size()); - assertNull(cursor.toList().get(0).get("startTime")); - assertNotNull(cursor.toList().get(1).get("startTime")); - } - - @Test - public void testIssue93() { - NitriteCollection coll = db.getCollection("orderByOnNullableColumn2"); - - coll.remove(ALL); - - Document doc = createDocument().put("id", "test-2").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - doc = createDocument().put("id", "test-1").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - DocumentCursor cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending); - assertEquals(2, cursor.size()); - } - - @Test - public void testNullOrderWithAllNull() { - NitriteCollection coll = db.getCollection("test"); - - coll.remove(ALL); - - Document doc = createDocument().put("id", "test-2").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - doc = createDocument().put("id", "test-1").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - DocumentCursor cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending); - assertEquals(2, cursor.size()); - - DocumentCursor cursor2 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.Default); - assertEquals(2, cursor2.size()); - - assertThat(cursor.toList(), is(cursor2.toList())); - - DocumentCursor cursor3 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.First); - assertEquals(2, cursor3.size()); - - assertThat(cursor.toList(), is(cursor3.toList())); - - DocumentCursor cursor4 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.Last); - assertEquals(2, cursor4.size()); - - assertThat(cursor.toList(), is(cursor4.toList())); - - DocumentCursor cursor5 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.Last); - assertEquals(2, cursor5.size()); - - assertThat(cursor.toList(), is(cursor5.toList())); - - DocumentCursor cursor6 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.First); - assertEquals(2, cursor6.size()); - - assertThat(cursor.toList(), is(cursor6.toList())); - - DocumentCursor cursor7 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.Default); - assertEquals(2, cursor7.size()); - - assertThat(cursor.toList(), is(cursor7.toList())); - } - - @Test - public void testNullOrder() { - NitriteCollection coll = db.getCollection("test"); - try { - coll.createIndex("startTime", IndexOptions.indexOptions(IndexType.NonUnique)); - } catch (IndexingException e) { - // ignore - } - - coll.remove(ALL); - - Document doc1 = createDocument().put("id", "test-1").put("group", "groupA"); - assertEquals(1, coll.insert(doc1).getAffectedCount()); - - Document doc2 = createDocument().put("id", "test-2").put("group", "groupA").put("startTime", DateTime.now()); - assertEquals(1, coll.insert(doc2).getAffectedCount()); - - Document doc3 = createDocument().put("id", "test-3").put("group", "groupA").put("startTime", DateTime.now().plusMinutes(1)); - assertEquals(1, coll.insert(doc3).getAffectedCount()); - - DocumentCursor cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc3, doc2, doc1), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.First); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc1, doc3, doc2), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.Default); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc3, doc2, doc1), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.Last); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc3, doc2, doc1), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.First); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc1, doc2, doc3), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.Default); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc1, doc2, doc3), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.Last); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc2, doc3, doc1), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - } - - @Test - public void testFindFilterInvalidAccessor() { - insert(); - DocumentCursor cursor = collection.find(where("lastName.name").eq("ln2")); - assertEquals(cursor.size(), 0); - } - - @Test - public void testIssue144() { - Document doc1 = createDocument().put("id", "test-1").put("fruit", "Apple"); - Document doc2 = createDocument().put("id", "test-2").put("fruit", "Ôrange"); - Document doc3 = createDocument().put("id", "test-3").put("fruit", "Pineapple"); - - NitriteCollection coll = db.getCollection("test"); - coll.insert(doc1, doc2, doc3); - - DocumentCursor cursor = coll.find().sort("fruit", SortOrder.Ascending, - Collator.getInstance(Locale.FRANCE)); - assertEquals(cursor.toList().get(1).get("fruit"), "Ôrange"); - } - - @Test - public void testIdSet() { - insert(); - DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("lastName").eq("ln1")); - assertEquals(cursor.size(), 1); - - Document byId = cursor.iterator().next(); - assertEquals(byId.get("lastName"), "ln1"); - } - - @Test - public void testCollectionField() { - Document document = createDocument("name", "John") - .put("tags", new Document[]{ - createDocument("type", "example").put("other", "value"), - createDocument("type", "another-example").put("other", "some-other-value") - }); - - NitriteCollection example = db.getCollection("example"); - example.insert(document); - - document = createDocument("name", "Jane") - .put("tags", new Document[]{ - createDocument("type", "example2").put("other", "value2"), - createDocument("type", "another-example2").put("other", "some-other-value2") - }); - example.insert(document); - - DocumentCursor cursor = example.find(where("tags").elemMatch(where("type").eq("example"))); - for (Document doc : cursor) { - assertNotNull(doc); - assertEquals(doc.get("name"), "John"); - } - } - - @Test - public void testBetweenFilter() { - Document doc1 = createDocument("age", 31).put("tag", "one"); - Document doc2 = createDocument("age", 32).put("tag", "two"); - Document doc3 = createDocument("age", 33).put("tag", "three"); - Document doc4 = createDocument("age", 34).put("tag", "four"); - Document doc5 = createDocument("age", 35).put("tag", "five"); - - NitriteCollection collection = db.getCollection("tag"); - collection.insert(doc1, doc2, doc3, doc4, doc5); - collection.createIndex("age", IndexOptions.indexOptions(IndexType.Unique)); - - DocumentCursor cursor = collection.find(where("age").between(31, 35)); - assertEquals(cursor.size(), 5); - - cursor = collection.find(where("age").between(31, 35, false)); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("age").between(31, 35, false, true)); - assertEquals(cursor.size(), 4); - - cursor = collection.find(where("age").between(31, 35, false).not()); - assertEquals(cursor.size(), 2); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionIndexNegativeTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionIndexNegativeTest.java deleted file mode 100644 index 3c0828520..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionIndexNegativeTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.exceptions.IndexingException; -import org.dizitart.no2.exceptions.UniqueConstraintException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.junit.Test; - -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionIndexNegativeTest extends BaseCollectionTest { - - @Test(expected = UniqueConstraintException.class) - public void testCreateInvalidUniqueIndex() { - collection.createIndex("lastName", IndexOptions.indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("lastName")); - insert(); - } - - @Test(expected = UniqueConstraintException.class) - public void testCreateIndexOnArray() { - collection.createIndex("data", IndexOptions.indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("data")); - // data array field has repetition, so unique constraint exception - insert(); - } - - @Test - public void testCreateOnInvalidField() { - insert(); - collection.createIndex("my-value", IndexOptions.indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("my-value")); - } - - @Test(expected = IndexingException.class) - public void testCreateFullTextOnNonTextField() { - insert(); - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("birthDay")); - } - - @Test(expected = IndexingException.class) - public void testDropIndexOnNonIndexedField() { - collection.dropIndex("data"); - } - - @Test(expected = IndexingException.class) - public void testRebuildIndexInvalid() { - collection.rebuildIndex("unknown", true); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionIndexTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionIndexTest.java deleted file mode 100644 index 161e52626..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionIndexTest.java +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.IndexingException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexEntry; -import org.dizitart.no2.index.IndexType; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import java.util.concurrent.Callable; - -import static org.awaitility.Awaitility.await; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionIndexTest extends BaseCollectionTest { - - @Test - public void testCreateIndex() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("firstName")); - - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - assertTrue(collection.hasIndex("lastName")); - - collection.createIndex("body", indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("body")); - - collection.createIndex("birthDay", null); - assertTrue(collection.hasIndex("birthDay")); - - insert(); - } - - @Test - public void testListIndexes() { - assertEquals(collection.listIndices().size(), 0); - - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("firstName")); - - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - assertTrue(collection.hasIndex("lastName")); - - collection.createIndex("body", indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("body")); - - assertEquals(collection.listIndices().size(), 3); - } - - @Test - public void testDropIndex() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("firstName")); - - collection.dropIndex("firstName"); - assertFalse(collection.hasIndex("firstName")); - } - - @Test - public void testDropAllIndexes() { - collection.dropAllIndices(); - - testCreateIndex(); - assertEquals(collection.listIndices().size(), 4); - - collection.dropAllIndices(); - assertEquals(collection.listIndices().size(), 0); - } - - @Test - public void testHasIndex() { - assertFalse(collection.hasIndex("lastName")); - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - assertTrue(collection.hasIndex("lastName")); - - assertFalse(collection.hasIndex("body")); - collection.createIndex("body", indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("body")); - } - - @Test - public void testDeleteWithIndex() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("body", indexOptions(IndexType.Fulltext)); - - insert(); - - WriteResult result = collection.remove(where("firstName").eq("fn1")); - assertEquals(result.getAffectedCount(), 1); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 2); - - result = collection.remove(where("body").text("Lorem")); - assertEquals(result.getAffectedCount(), 1); - - cursor = collection.find(); - assertEquals(cursor.size(), 1); - } - - @Test - public void testCreateIndexAsync() { - insert(); - collection.createIndex("body", indexOptions(IndexType.Fulltext, true)); - assertTrue(collection.isIndexing("body")); - - await().until(bodyIndexingCompleted()); - } - - @Test - public void testRebuildIndex() { - collection.createIndex("body", indexOptions(IndexType.Fulltext, false)); - insert(); - Collection indices = collection.listIndices(); - for (IndexEntry idx : indices) { - collection.rebuildIndex(idx.getField(), false); - } - } - - @Test - public void testRebuildIndexAsync() { - collection.createIndex("body", indexOptions(IndexType.Fulltext, true)); - insert(); - await().until(bodyIndexingCompleted()); - - Collection indices = collection.listIndices(); - for (IndexEntry idx : indices) { - collection.rebuildIndex(idx.getField(), true); - await().until(bodyIndexingCompleted()); - } - } - - @Test - public void testRebuildIndexOnRunningIndex() { - collection.createIndex("body", indexOptions(IndexType.Fulltext, false)); - Collection indices = collection.listIndices(); - IndexEntry idx = indices.iterator().next(); - insert(); - collection.rebuildIndex(idx.getField(), true); - - boolean error = false; - try { - collection.rebuildIndex(idx.getField(), true); - } catch (IndexingException ie) { - error = true; - } finally { - assertTrue(error); - await().until(bodyIndexingCompleted()); - } - } - - private Callable bodyIndexingCompleted() { - return () -> !collection.isIndexing("body"); - } - - @Test - public void testNullValueInIndexedField() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("birthDay", indexOptions(IndexType.NonUnique)); - insert(); - - Document document = createDocument("firstName", null) - .put("lastName", "ln1") - .put("birthDay", null) - .put("data", new byte[]{1, 2, 3}) - .put("list", new ArrayList() {{ - add("one"); - add("two"); - add("three"); - }}) - .put("body", "a quick brown fox jump over the lazy dog"); - - collection.insert(document); - } - - @Test - public void testDropAllAndCreateIndex() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("firstName")); - collection.dropAllIndices(); - assertFalse(collection.hasIndex("firstName")); - - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("firstName")); - - collection = db.getCollection("test"); - assertTrue(collection.hasIndex("firstName")); - } - - @Test - public void testIssue178() { - collection.dropAllIndices(); - collection.remove(Filter.ALL); - - Document doc1 = createDocument("field", 5); - Document doc2 = createDocument("field", 4.3); - Document doc3 = createDocument("field", 0.03); - Document doc4 = createDocument("field", 4); - Document doc5 = createDocument("field", 5.0); - - collection.insert(doc1, doc2, doc3, doc4, doc5); - - DocumentCursor cursor = collection.find(where("field").eq(5)); - assertEquals(cursor.size(), 1); - - collection.createIndex("field", indexOptions(IndexType.NonUnique)); - - cursor = collection.find(where("field").eq(5)); - assertEquals(cursor.size(), 1); - } - - @Test - public void testIndexEvent() { - NitriteCollection collection = db.getCollection("index-test"); - Random random = new Random(); - for (int i = 0; i < 10000; i++) { - Document document = createDocument("first", random.nextInt()) - .put("second", random.nextDouble()); - collection.insert(document); - } - - collection.subscribe(eventInfo -> { - switch (eventInfo.getEventType()) { - case Insert: - fail("wrong event Insert"); - break; - case Update: - fail("wrong event Update"); - break; - case Remove: - fail("wrong event Remove"); - break; - case IndexStart: - case IndexEnd: - break; - } - assertTrue(eventInfo.getItem() instanceof String); - System.out.println(eventInfo.getEventType() + " for field " + eventInfo.getItem()); - }); - - collection.createIndex("first", indexOptions(IndexType.NonUnique)); - assertEquals(collection.find().size(), 10000); - - collection.createIndex("second", indexOptions(IndexType.NonUnique)); - assertEquals(collection.find().size(), 10000); - } - - @Test - public void testIndexAndSearchOnNullValues() { - NitriteCollection collection = db.getCollection("index-on-null"); - collection.insert(createDocument("first", null).put("second", 123).put("third", new Integer[]{1, 2, null})); - collection.insert(createDocument("first", "abcd").put("second", 456).put("third", new int[]{3, 1})); - collection.insert(createDocument("first", "xyz").put("second", 789).put("third", null)); - - collection.createIndex("first", indexOptions(IndexType.Unique)); - assertEquals(collection.find(where("first").eq(null)).size(), 1); - - collection.createIndex("third", indexOptions(IndexType.NonUnique)); - assertEquals(collection.find(where("third").eq(null)).size(), 2); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionInsertNegativeTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionInsertNegativeTest.java deleted file mode 100644 index 90c1ba0ef..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionInsertNegativeTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.UniqueConstraintException; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionInsertNegativeTest extends BaseCollectionTest { - @Test(expected = UniqueConstraintException.class) - public void testMultipleInsert() { - WriteResult result = collection.insert(doc1, doc2, doc3); - assertEquals(result.getAffectedCount(), 3); - Document document = collection.find().firstOrNull(); - collection.insert(document); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionInsertTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionInsertTest.java deleted file mode 100644 index f7d538c31..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionInsertTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.common.WriteResult; -import org.junit.Test; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.common.Constants.DOC_ID; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -public class CollectionInsertTest extends BaseCollectionTest { - - @Test - public void testInsert() { - WriteResult result = collection.insert(doc1, doc2, doc3); - assertEquals(result.getAffectedCount(), 3); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - - for (Document document : cursor) { - assertNotNull(document.get("firstName")); - assertNotNull(document.get("lastName")); - assertNotNull(document.get("birthDay")); - assertNotNull(document.get("data")); - assertNotNull(document.get("body")); - assertNotNull(document.get(DOC_ID)); - } - } - - @Test - public void testInsertHeteroDocs() { - Document document = createDocument("test", "Nitrite Test"); - - WriteResult result = collection.insert(doc1, doc2, doc3, document); - assertEquals(result.getAffectedCount(), 4); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionJoinTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionJoinTest.java deleted file mode 100644 index 2d8ef5ac5..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionJoinTest.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import lombok.extern.slf4j.Slf4j; -import org.dizitart.no2.common.Lookup; -import org.dizitart.no2.common.RecordStream; -import org.junit.Before; -import org.junit.Test; - -import java.util.Collection; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -@Slf4j -public class CollectionJoinTest extends BaseCollectionTest { - private NitriteCollection foreignCollection; - - @Before - @Override - public void setUp() { - try { - super.setUp(); - foreignCollection = db.getCollection("foreign"); - foreignCollection.remove(ALL); - - Document fdoc1 = createDocument("fName", "fn1") - .put("address", "ABCD Street") - .put("telephone", "123456789"); - - Document fdoc2 = createDocument("fName", "fn2") - .put("address", "XYZ Street") - .put("telephone", "000000000"); - - Document fdoc3 = createDocument("fName", "fn2") - .put("address", "Some other Street") - .put("telephone", "7893141321"); - - foreignCollection.insert(fdoc1, fdoc2, fdoc3); - } catch (Throwable t) { - log.error("Error while initializing test database", t); - } - } - - @Test - @SuppressWarnings("unchecked") - public void testJoinAll() { - insert(); - - Lookup lookup = new Lookup(); - lookup.setLocalField("firstName"); - lookup.setForeignField("fName"); - lookup.setTargetField("personalDetails"); - - RecordStream result = collection.find().join(foreignCollection.find(), lookup); - assertEquals(result.size(), 3); - - for (Document document : result) { - if (document.get("firstName") == "fn1") { - Collection personalDetails = (Collection) document.get("personalDetails"); - assertNotNull(personalDetails); - assertEquals(personalDetails.size(), 1); - Object[] details = personalDetails.toArray(); - assertEquals(((Document) details[0]).get("telephone"), "123456789"); - } else if (document.get("firstName") == "fn2") { - Collection personalDetails = (Collection) document.get("personalDetails"); - assertNotNull(personalDetails); - assertEquals(personalDetails.size(), 2); - Object[] details = personalDetails.toArray(); - for (Object o : details) { - Document d = (Document) o; - if (d.get("address").equals("XYZ Street")) { - assertEquals(d.get("telephone"), "000000000"); - } else { - assertEquals(d.get("telephone"), "7893141321"); - } - } - } else if (document.get("firstName") == "fn3") { - assertNull(document.get("personalDetails")); - } - System.out.println(document); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionUpdateTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionUpdateTest.java deleted file mode 100644 index aa1c3cee7..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/CollectionUpdateTest.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.NotIdentifiableException; -import org.dizitart.no2.exceptions.UniqueConstraintException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexType; -import org.junit.Test; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.*; - -public class CollectionUpdateTest extends BaseCollectionTest { - - @Test - public void testUpdate() { - insert(); - - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertEquals(document.get("lastName"), "ln1"); - } - - WriteResult updateResult = collection.update(where("firstName").eq("fn1"), - createDocument("lastName", "new-last-name")); - assertEquals(updateResult.getAffectedCount(), 1); - - cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertEquals(document.get("lastName"), "new-last-name"); - } - } - - @Test(expected = NotIdentifiableException.class) - public void testUpsertWithoutId() { - insert(); - Document update = createDocument("lastName", "ln4"); - WriteResult writeResult = collection.update(update, false); - assertEquals(writeResult.getAffectedCount(), 0); - assertEquals(collection.size(), 3); - } - - @Test - public void testUpsert() { - insert(); - assertEquals(collection.size(), 3); - - Document update = createDocument("lastName", "ln4"); - WriteResult writeResult = collection.update(update, true); - assertEquals(writeResult.getAffectedCount(), 1); - assertEquals(collection.size(), 4); - - Document document = collection.find(where("lastName").eq("ln4")) - .firstOrNull(); - assertTrue(isSimilar(document, update, "lastName")); - } - - @Test - public void testOptionUpsert() { - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - - WriteResult updateResult = collection.update(where("firstName").eq("fn1"), - doc1, UpdateOptions.updateOptions(true)); - assertEquals(updateResult.getAffectedCount(), 1); - - cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertTrue(isSimilar(document, doc1, "firstName", "lastName", "birthDay", "data", "list", "body")); - } - } - - @Test - public void testUpdateMultiple() { - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - - insert(); - - Document document = createDocument("lastName", "newLastName1"); - WriteResult updateResult = collection.update(where("firstName").eq("fn1").not(), - document); - assertEquals(updateResult.getAffectedCount(), 2); - - cursor = collection.find(where("lastName").eq("newLastName1")); - assertEquals(cursor.size(), 2); - } - - @Test - public void testUpdateWithOptionsUpsertFalse() { - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - - UpdateOptions updateOptions = new UpdateOptions(); - updateOptions.setInsertIfAbsent(false); - - WriteResult updateResult = collection.update(where("firstName").eq("fn1"), - doc1, updateOptions); - assertEquals(updateResult.getAffectedCount(), 0); - - cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - } - - @Test - public void testUpdateMultipleWithJustOnceFalse() { - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - - insert(); - - UpdateOptions updateOptions = new UpdateOptions(); - updateOptions.setJustOnce(false); - - Document document = createDocument("lastName", "newLastName1"); - WriteResult updateResult = collection.update(where("firstName").eq("fn1").not(), - document, updateOptions); - assertEquals(updateResult.getAffectedCount(), 2); - - cursor = collection.find(where("lastName").eq("newLastName1")); - assertEquals(cursor.size(), 2); - } - - @Test - public void testUpdateMultipleWithJustOnceTrue() { - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - - insert(); - - UpdateOptions updateOptions = new UpdateOptions(); - updateOptions.setJustOnce(true); - - Document document = createDocument("lastName", "newLastName1"); - collection.update(where("firstName").eq("fn1").not(), - document, updateOptions); - } - - @Test - public void testUpdateWithNewField() { - insert(); - - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertEquals(document.get("lastName"), "ln1"); - } - - WriteResult updateResult = collection.update(where("firstName").eq("fn1"), - createDocument("new-value", "new-value-value")); - assertEquals(updateResult.getAffectedCount(), 1); - - cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertEquals(document.get("new-value"), "new-value-value"); - } - } - - @Test - public void testUpdateInvalidFilter() { - insert(); - - DocumentCursor cursor = collection.find(where("lastName").eq("ln1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertEquals(document.get("firstName"), "fn1"); - } - - // to check if NitriteId is valid. - WriteResult updateResult = collection.update(where("some-value").eq("some-value"), - createDocument("lastName", "new-last-name")); - assertEquals(updateResult.getAffectedCount(), 0); - } - - @Test - public void updateAfterAttributeRemoval() { - NitriteCollection coll = db.getCollection("test_updateAfterAttributeRemoval"); - coll.remove(Filter.ALL); - - Document doc = createDocument().put("id", "test-1").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - Document savedDoc1 = coll.find().firstOrNull(); - assertNotNull(savedDoc1); - - Document clonedDoc1 = savedDoc1.clone(); - assertEquals(savedDoc1, clonedDoc1); - - clonedDoc1.put("group", null); -// clonedDoc1.remove("group"); - assertEquals(1, coll.update(clonedDoc1).getAffectedCount()); - - Document savedDoc2 = coll.find(Filter.ALL).firstOrNull(); - assertNotNull(savedDoc2); - assertNull(savedDoc2.get("group")); - } - - @Test(expected = NotIdentifiableException.class) - public void testUpdateWithoutId() { - NitriteCollection collection = db.getCollection("test"); - Document document = createDocument("test", "test123"); - collection.update(document); - } - - @Test(expected = NotIdentifiableException.class) - public void testRemoveWithoutId() { - NitriteCollection collection = db.getCollection("test"); - Document document = createDocument("test", "test123"); - collection.remove(document); - } - - @Test(expected = NitriteIOException.class) - public void testRegisterListenerAfterDrop() { - NitriteCollection collection = db.getCollection("test"); - collection.drop(); - collection.subscribe(changeInfo -> fail("should not happen")); - } - - @Test(expected = NitriteIOException.class) - public void testRegisterListenerAfterClose() { - NitriteCollection collection = db.getCollection("test"); - collection.close(); - collection.subscribe(changeInfo -> fail("should not happen")); - } - - @Test(expected = UniqueConstraintException.class) - public void testIssue151() { - Document doc1 = createDocument().put("id", "test-1").put("fruit", "Apple"); - Document doc2 = createDocument().put("id", "test-2").put("fruit", "Ôrange"); - NitriteCollection coll = db.getCollection("test"); - coll.insert(doc1, doc2); - - coll.createIndex("fruit", indexOptions(IndexType.Unique)); - - assertEquals(coll.find(where("fruit").eq("Apple")).size(), 1); - - Document doc3 = coll.find(where("id").eq("test-2")).firstOrNull(); - - doc3.put("fruit", "Apple"); - coll.update(doc3); - - assertEquals(coll.find(where("fruit").eq("Apple")).size(), 1); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/NitriteCollectionTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/NitriteCollectionTest.java deleted file mode 100644 index 120ed4b8e..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/NitriteCollectionTest.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.Retry; -import org.dizitart.no2.collection.meta.Attributes; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import static org.dizitart.no2.TestUtil.createDb; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee - */ -public class NitriteCollectionTest { - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testAttributes() { - db = createDb(); - NitriteCollection collection = db.getCollection("test"); - - Attributes attributes = new Attributes("test"); - collection.setAttributes(attributes); - - assertEquals(collection.getAttributes(), attributes); - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/operation/DocumentCursorTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/operation/DocumentCursorTest.java deleted file mode 100644 index bc23b70e5..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/operation/DocumentCursorTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection.operation; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.Retry; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.util.Iterator; - -import static org.dizitart.no2.TestUtil.createDb; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee. - */ -public class DocumentCursorTest { - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testFindResult() { - db = createDb(); - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("first", "second")); - - DocumentCursor result = collection.find(); - assertTrue(result instanceof DocumentCursorImpl); - } - - @Test(expected = InvalidOperationException.class) - public void testIteratorRemove() { - db = createDb(); - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("first", "second")); - - DocumentCursor cursor = collection.find(); - Iterator iterator = cursor.iterator(); - if (iterator.hasNext()) { - iterator.next(); - iterator.remove(); - } - } - - @Test - public void testValidateProjection() { - db = createDb(); - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("first", "second")); - - Document projection = createDocument("first", createDocument("second", null)); - RecordStream project = collection.find().project(projection); - assertNotNull(project); - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/operation/JoinedDocumentStreamTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/operation/JoinedDocumentStreamTest.java deleted file mode 100644 index 6cd178a39..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/collection/operation/JoinedDocumentStreamTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection.operation; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.Retry; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.Lookup; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.util.Iterator; - -import static org.dizitart.no2.TestUtil.createDb; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee - */ -public class JoinedDocumentStreamTest { - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testFindResult() { - db = createDb(); - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("first", "second")); - - RecordStream result = collection.find().join(collection.find(), new Lookup()); - assertTrue(result instanceof JoinedDocumentStream); - } - - @Test(expected = InvalidOperationException.class) - public void testIteratorRemove() { - db = createDb(); - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("first", "second")); - - RecordStream cursor = collection.find().join(collection.find(), new Lookup()); - assertNotNull(cursor.toString()); - Iterator iterator = cursor.iterator(); - if (iterator.hasNext()) { - iterator.next(); - iterator.remove(); - } - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/common/event/EventTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/common/event/EventTest.java deleted file mode 100644 index 9ad63d60f..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/common/event/EventTest.java +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.common.event; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.Retry; -import org.dizitart.no2.collection.events.EventType; -import org.dizitart.no2.mvstore.MVStoreModule; -import org.dizitart.no2.mvstore.MVStoreModuleBuilder; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.data.Employee; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Collection; -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.awaitility.Awaitility.await; -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -@RunWith(Parameterized.class) -public class EventTest { - @Parameterized.Parameter - public boolean inMemory = false; - @Parameterized.Parameter(value = 1) - public boolean isProtected = false; - @Parameterized.Parameter(value = 2) - public boolean isCompressed = false; - @Parameterized.Parameter(value = 3) - public boolean isAutoCommit = false; - - private final String fileName = getRandomTempDbFile(); - private Nitrite db; - private ObjectRepository employeeRepository; - private SampleListenerCollection listener; - - @Rule - public Retry retry = new Retry(3); - - @Parameterized.Parameters(name = "InMemory = {0}, Protected = {1}, " + - "Compressed = {2}, AutoCommit = {3}") - public static Collection data() { - return Arrays.asList(new Object[][]{ - {false, false, false, false}, - {false, false, false, true}, - {false, false, true, false}, - {false, false, true, true}, - {false, true, false, false}, - {false, true, false, true}, - {false, true, true, false}, - {false, true, true, true}, - {true, false, false, false}, - {true, false, false, true}, - {true, false, true, false}, - {true, false, true, true}, - {true, true, false, false}, - {true, true, false, true}, - {true, true, true, false}, - {true, true, true, true}, - }); - } - - @Before - public void setUp() { - MVStoreModuleBuilder builder = MVStoreModule.withConfig(); - - if (isCompressed) { - builder.compress(true); - } - - if (!isAutoCommit) { - builder.autoCommit(false); - } - - if (!inMemory) { - builder.filePath(fileName); - } - - MVStoreModule storeModule = builder.build(); - NitriteBuilder nitriteBuilder = Nitrite.builder() - .fieldSeparator(".") - .loadModule(storeModule); - - if (isProtected) { - db = nitriteBuilder.openOrCreate("test-user", "test-password"); - } else { - db = nitriteBuilder.openOrCreate(); - } - - employeeRepository = db.getRepository(Employee.class); - listener = new SampleListenerCollection(); - employeeRepository.subscribe(listener); - } - - @Test - public void testInsert() { - Employee employee = new Employee(); - employee.setEmpId(1L); - employeeRepository.insert(employee); - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); - assertEquals(listener.getAction(), EventType.Insert); - assertNotNull(listener.getItem()); - } - - @Test - public void testUpdate() { - Employee e = new Employee(); - e.setEmpId(1L); - e.setAddress("abcd"); - employeeRepository.insert(e); - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); - assertEquals(listener.getAction(), EventType.Insert); - assertNotNull(listener.getItem()); - - e.setAddress("xyz"); - employeeRepository.update(where("empId").eq(1L), e); - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Update)); - assertEquals(listener.getAction(), EventType.Update); - assertNotNull(listener.getItem()); - - Employee byId = employeeRepository.getById(1L); - assertEquals(byId.getAddress(), "xyz"); - } - - @Test - public void testUpsert() { - Employee e = new Employee(); - e.setEmpId(1L); - e.setAddress("abcd"); - - employeeRepository.update(where("empId").eq(1), e, true); - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); - assertEquals(listener.getAction(), EventType.Insert); - assertNotNull(listener.getItem()); - } - - @Test - public void testDelete() { - Employee e = new Employee(); - e.setEmpId(1L); - e.setAddress("abcd"); - - employeeRepository.insert(e); - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); - - employeeRepository.remove(where("empId").eq(1L)); - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Remove)); - - System.out.println("Action - " + listener.getAction()); - assertEquals(listener.getAction(), EventType.Remove); - assertNotNull(listener.getItem()); - } - - @Test - public void testDrop() { - employeeRepository.drop(); - assertNull(listener.getItem()); - } - - @Test - public void testClose() { - if (employeeRepository.isOpen()) { - employeeRepository.close(); - } - assertNull(listener.getItem()); - } - - @Test - public void testDeregister() { - employeeRepository.unsubscribe(listener); - Employee e = new Employee(); - e.setEmpId(1L); - e.setAddress("abcd"); - - employeeRepository.insert(e); - assertNull(listener.getAction()); - assertNull(listener.getItem()); - } - - @Test - public void testMultipleListeners() { - final AtomicInteger count = new AtomicInteger(0); - employeeRepository.subscribe(changeInfo -> count.incrementAndGet()); - - employeeRepository.subscribe(changeInfo -> count.incrementAndGet()); - - Employee e = new Employee(); - e.setEmpId(1L); - e.setAddress("abcd"); - employeeRepository.insert(e); - - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); - assertEquals(count.get(), 2); - } - - @Test - public void testSingleEventListener() { - final AtomicInteger count = new AtomicInteger(0); - employeeRepository.subscribe(changeInfo -> count.incrementAndGet()); - - employeeRepository = db.getRepository(Employee.class); - Employee e = new Employee(); - e.setEmpId(1L); - e.setAddress("abcd"); - employeeRepository.insert(e); - - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); - assertEquals(count.get(), 1); - } - - @After - public void clear() throws IOException { - if (employeeRepository != null) { - if (!employeeRepository.isDropped() - && employeeRepository.isOpen()) { - employeeRepository.remove(ALL); - employeeRepository.unsubscribe(listener); - employeeRepository.close(); - } - } - - if (db != null) { - db.commit(); - db.close(); - } - - if (!inMemory) { - Files.delete(Paths.get(fileName)); - } - } - - private Callable listenerPrepared(final EventType action) { - return () -> listener.getAction() == action; - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/common/event/SampleListenerCollection.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/common/event/SampleListenerCollection.java deleted file mode 100644 index debd67fee..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/common/event/SampleListenerCollection.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.common.event; - -import lombok.Getter; -import org.dizitart.no2.collection.events.CollectionEventInfo; -import org.dizitart.no2.collection.events.CollectionEventListener; -import org.dizitart.no2.collection.events.EventType; - -/** - * @author Anindya Chatterjee. - */ -@Getter -class SampleListenerCollection implements CollectionEventListener { - private EventType action; - private Object item; - - @Override - public void onEvent(CollectionEventInfo eventInfo) { - if (eventInfo != null) { - this.action = eventInfo.getEventType(); - this.item = eventInfo.getItem(); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/CustomFilterTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/CustomFilterTest.java new file mode 100644 index 000000000..75a15f156 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/CustomFilterTest.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.dizitart.no2.integration.collection.BaseCollectionTest; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee. + */ +public class CustomFilterTest extends BaseCollectionTest { + + @Test + public void testCustomFilter() { + insert(); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "firstName"); + DocumentCursor cursor = collection.find(element -> element.getSecond().get("firstName", String.class) + .equalsIgnoreCase("FN1")); + + assertEquals(cursor.size(), 1); + assertEquals(cursor.firstOrNull().get("firstName"), "fn1"); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/DbWriteCloseReadTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/DbWriteCloseReadTest.java new file mode 100644 index 000000000..ccf825dfe --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/DbWriteCloseReadTest.java @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.index.IndexType; +import org.junit.Rule; +import org.junit.Test; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.collection.FindOptions.orderBy; +import static org.dizitart.no2.filters.Filter.*; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class DbWriteCloseReadTest { + private final String fileName = TestUtil.getRandomTempDbFile(); + private Nitrite db; + private volatile boolean writeCompleted = false; + + @Rule + public Retry retry = new Retry(3); + + @Test + public void testWriteCloseRead() throws Exception { + try { + createDb(); + writeCollection(); + writeIndex(); + insertInCollection(); + } catch (ParseException pe) { + // ignore + } finally { + writeCompleted = true; + } + + try { + assertTrue(writeCompleted); + readCollection(); + } catch (Exception e) { + fail("collection read failed - " + e.getMessage()); + } finally { + deleteDb(); + } + } + + void createDb() { + db = TestUtil.createDb(fileName); + db.close(); + } + + void writeCollection() { + NitriteCollection collection; + + db = TestUtil.createDb(fileName); + + collection = db.getCollection("test"); + collection.remove(ALL); + db.close(); + } + + void writeIndex() { + NitriteCollection collection; + + db = TestUtil.createDb(fileName); + + collection = db.getCollection("test"); + collection.remove(ALL); + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + collection.createIndex("firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + db.close(); + } + + void insertInCollection() throws Exception { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); + + Document doc1 = createDocument("firstName", "fn1") + .put("lastName", "ln1") + .put("birthDay", simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + .put("data", new byte[]{1, 2, 3}) + .put("body", "a quick brown fox jump over the lazy dog"); + Document doc2 = createDocument("firstName", "fn2") + .put("lastName", "ln2") + .put("birthDay", simpleDateFormat.parse("2010-06-12T16:02:48.440Z")) + .put("data", new byte[]{3, 4, 3}) + .put("body", "quick hello world from nitrite"); + Document doc3 = createDocument("firstName", "fn3") + .put("lastName", "ln2") + .put("birthDay", simpleDateFormat.parse("2014-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + + NitriteCollection collection; + + db = TestUtil.createDb(fileName); + + collection = db.getCollection("test"); + + WriteResult result = collection.insert(doc1, doc2, doc3); + assertEquals(result.getAffectedCount(), 3); + + db.commit(); + db.close(); + } + + void readCollection() throws Exception { + NitriteCollection collection; + + db = TestUtil.createDb(fileName); + + collection = db.getCollection("test"); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").gt(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").gte(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lt(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").lte(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lte(new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").lt(new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").gt(new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("birthDay").gte(new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("birthDay").lte(new Date()).and(where("firstName").eq("fn1"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").lte(new Date()).or(where("firstName").eq("fn12"))); + assertEquals(cursor.size(), 3); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + )); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + ).not()); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").eq((byte) 4)); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").lt(4)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("firstName").notIn("fn1", "fn2")); + assertEquals(cursor.size(), 1); + + collection.createIndex("birthDay"); + cursor = collection.find(orderBy("birthDay", SortOrder.Descending).skip(1).limit(2)); + assertEquals(cursor.size(), 2); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(TestUtil.isSorted(dateList, false)); + + cursor = collection.find(where("body").text("Lorem")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("body").text("quick")); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("body").text("nosql")); + assertEquals(cursor.size(), 0); + + db.close(); + } + + void deleteDb() { + if (db != null && !db.isClosed()) { + db.close(); + } + TestUtil.deleteDb(fileName); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/DocumentMetadataTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/DocumentMetadataTest.java new file mode 100644 index 000000000..15d01451f --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/DocumentMetadataTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.dizitart.no2.integration.collection.BaseCollectionTest; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.events.EventType; +import org.junit.Test; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee. + */ +public class DocumentMetadataTest extends BaseCollectionTest { + @Test + public void testTimeStamp() { + Document document = createDocument("test_key", "test_value"); + assertEquals(document.getRevision().intValue(), 0); + assertEquals(document.getLastModifiedSinceEpoch().longValue(), 0L); + + collection.insert(document); + document = collection.find().firstOrNull(); + + assertEquals(document.getRevision().intValue(), 1); + assertTrue(document.getLastModifiedSinceEpoch() > 0); + + long previous = document.getRevision(); + + DocumentCursor cursor = collection.find(where("test_key").eq("test_value")); + document = cursor.firstOrNull(); + document.put("another_key", "another_value"); + + collection.update(document); + cursor = collection.find(where("test_key").eq("test_value")); + document = cursor.firstOrNull(); + + assertTrue(document.getRevision() > previous); + + final long time = document.getRevision(); + final Document removed = document; + + collection.subscribe(changeInfo -> { + if (changeInfo.getEventType() == EventType.Remove) { + assertTrue(removed.getRevision() > time); + } + }); + + collection.remove(document); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/MultiThreadedTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/MultiThreadedTest.java new file mode 100644 index 000000000..11a7b35bf --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/MultiThreadedTest.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.concurrent.ThreadPoolManager; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.File; +import java.util.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + + +/** + * @author Anindya Chatterjee. + */ +@RunWith(Parameterized.class) +public class MultiThreadedTest { + private static final String fileName = TestUtil.getRandomTempDbFile(); + @Parameterized.Parameter + public boolean inMemory = false; + private NitriteCollection collection; + private final int threadCount = 20; + private final CountDownLatch latch = new CountDownLatch(threadCount); + private final int iterationCount = 100; + private final Random generator = new Random(); + private final AtomicInteger docCounter = new AtomicInteger(0); + private ExecutorService executor; + private Nitrite db; + + @Parameterized.Parameters(name = "InMemory = {0}") + public static Collection data() { + return Arrays.asList(new Object[][]{ + {false}, + {true} + }); + } + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + executor = ThreadPoolManager.getThreadPool(threadCount, "MultiThreadedTest"); + } + + @Test + public void testOperations() throws InterruptedException { + db = inMemory ? TestUtil.createDb() : TestUtil.createDb(fileName); + + collection = db.getCollection("test"); + collection.remove(Filter.ALL); + collection.createIndex("unixTime"); + db.commit(); + + for (int i = 0; i < threadCount; i++) { + executor.submit(() -> { + for (int j = 0; j < iterationCount; j++) { + try { + Document document = generate(); + collection.insert(document); + + if (j == iterationCount / 2 + && !collection.hasIndex("text") + && !collection.hasIndex("date")) { + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "text"); + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "date"); + } + + long unixTime = (long) document.get("unixTime"); + DocumentCursor cursor = collection.find(where("unixTime").eq(unixTime)); + assertTrue(cursor.size() >= 0); + + if (collection.hasIndex("text") && !collection.isIndexing("text")) { + String textData = (String) document.get("text"); + cursor = collection.find(where("text").text(textData)); + assertTrue(cursor.size() >= 0); + } + + assertTrue(collection.hasIndex("unixTime")); + } catch (Throwable e) { + System.out.println("Exception at thread " + + Thread.currentThread().getName() + " with iteration " + j); + e.printStackTrace(); + } + } + latch.countDown(); + }); + } + + latch.await(); + + db.commit(); + + assertTrue(collection.hasIndex("text")); + assertTrue(collection.hasIndex("date")); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), docCounter.get()); + + cursor = collection.find(where("unixTime").gt(1L)); + assertEquals(cursor.size(), docCounter.get()); + + db.close(); + } + + @After + public void cleanUp() throws Exception { + if (db != null && !db.isClosed()) { + db.close(); + } + + if (!inMemory) { + File dbFile = new File(fileName); + long fileSize = dbFile.length(); + assertTrue(fileSize > 0); + dbFile.delete(); + } + + if (executor != null && !executor.isShutdown()) { + executor.shutdown(); + executor = null; + } + } + + private synchronized Document generate() { + Document document = createDocument("unixTime", System.nanoTime() + docCounter.incrementAndGet()); + byte[] blob = new byte[1024]; + generator.nextBytes(blob); + document.put("blob", blob); + document.put("text", UUID.randomUUID().toString().replaceAll("-", " ")); + document.put("date", new Date()); + return document; + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/NitriteBuilderNegativeTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/NitriteBuilderNegativeTest.java new file mode 100644 index 000000000..036e480ce --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/NitriteBuilderNegativeTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.apache.commons.io.FileUtils; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.common.util.StringUtils; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.dizitart.no2.exceptions.NitriteIOException; +import org.dizitart.no2.mvstore.MVStoreModule; +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; + +import java.io.File; + +import static org.dizitart.no2.integration.TestUtil.createDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; + +/** + * @author Anindya Chatterjee. + */ +public class NitriteBuilderNegativeTest { + private Nitrite db; + private String filePath; + + @Rule + public Retry retry = new Retry(3); + + @Test(expected = NitriteIOException.class) + public void testCreateReadonlyDatabase() { + filePath = getRandomTempDbFile(); + + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(filePath) + .readOnly(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .openOrCreate(); + db.close(); + } + + @Test(expected = InvalidOperationException.class) + public void testCreateReadonlyInMemoryDatabase() { + MVStoreModule storeModule = MVStoreModule.withConfig() + .readOnly(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .openOrCreate(); + db.close(); + } + + @Test(expected = NitriteIOException.class) + public void testOpenWithLock() { + filePath = getRandomTempDbFile(); + + db = createDb(filePath); + db = createDb(filePath); + } + + @Test(expected = NitriteIOException.class) + public void testInvalidDirectory() { + filePath = "/ytgr/hfurh/frij.db"; + db = createDb(filePath); + } + + @After + public void cleanUp() { + if (db != null && !db.isClosed()) { + db.close(); + } + + if (!StringUtils.isNullOrEmpty(filePath)) { + FileUtils.deleteQuietly(new File(filePath)); + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/NitriteBuilderTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/NitriteBuilderTest.java new file mode 100644 index 000000000..fc5457ee5 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/NitriteBuilderTest.java @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteBuilder; +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.FieldValues; +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.dizitart.no2.exceptions.NitriteIOException; +import org.dizitart.no2.exceptions.NitriteSecurityException; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.NitriteIndexer; +import org.dizitart.no2.mvstore.MVStoreConfig; +import org.dizitart.no2.mvstore.MVStoreModule; +import org.dizitart.no2.mvstore.MVStoreModuleBuilder; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Index; +import org.dizitart.no2.store.StoreConfig; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.LinkedHashSet; +import java.util.Random; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.common.module.NitriteModule.module; +import static org.dizitart.no2.common.util.StringUtils.isNullOrEmpty; +import static org.dizitart.no2.integration.TestUtil.createDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class NitriteBuilderTest { + private String fakeFile; + private String filePath; + private Nitrite db; + private Nitrite fakeDb; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void startup() { + fakeFile = getRandomTempDbFile(); + filePath = getRandomTempDbFile(); + } + + @After + public void cleanup() throws IOException { + (new NitriteConfig()).fieldSeparator("."); + + if (db != null && !db.isClosed()) { + db.close(); + } + + if (Files.exists(Paths.get(filePath))) { + Files.delete(Paths.get(filePath)); + } + + if (fakeDb != null && !fakeDb.isClosed()){ + fakeDb.close(); + } + + if (Files.exists(Paths.get(fakeFile))) { + Files.delete(Paths.get(fakeFile)); + } + } + + @Test + public void testConfig() throws IOException { + MVStoreModuleBuilder builder = MVStoreModule.withConfig(); + builder.autoCommitBufferSize(1); + builder.compress(true); + builder.autoCommit(false); + builder.filePath(filePath); + + NitriteBuilder nitriteBuilder = Nitrite.builder(); + nitriteBuilder.loadModule(module(new CustomIndexer())); + nitriteBuilder.loadModule(builder.build()); + + db = nitriteBuilder.openOrCreate(); + NitriteConfig config = nitriteBuilder.getNitriteConfig(); + MVStoreConfig storeConfig = (MVStoreConfig) db.getStore().getStoreConfig(); + + assertEquals(storeConfig.autoCommitBufferSize(), 1); + assertEquals(config.findIndexer("Custom").getClass(), CustomIndexer.class); + assertFalse(storeConfig.autoCommit()); + assertFalse(storeConfig.autoCompact()); + assertTrue(storeConfig.compress()); + assertFalse(storeConfig.isReadOnly()); + assertFalse(storeConfig.isInMemory()); + assertFalse(isNullOrEmpty(storeConfig.filePath())); + + db.close(); + + builder = MVStoreModule.withConfig() + .readOnly(true) + .filePath(filePath); + + db = Nitrite.builder().loadModule(builder.build()).openOrCreate(); + + storeConfig = (MVStoreConfig) db.getStore().getStoreConfig(); + assertTrue(storeConfig.isReadOnly()); + db.close(); + + Files.delete(Paths.get(filePath)); + } + + @Test + public void testConfigWithFile() { + File file = new File(filePath); + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(file) + .compress(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .openOrCreate(); + StoreConfig storeConfig = db.getStore().getStoreConfig(); + + assertFalse(storeConfig.isInMemory()); + assertFalse(isNullOrEmpty(storeConfig.filePath())); + + NitriteCollection test = db.getCollection("test"); + assertNotNull(test); + + db.commit(); + db.close(); + + assertTrue(file.delete()); + } + + @Test + public void testConfigWithFileNull() { + File file = null; + MVStoreModule module = MVStoreModule.withConfig() + .filePath(file) + .build(); + + db = Nitrite.builder().loadModule(module).openOrCreate(); + StoreConfig storeConfig = db.getStore().getStoreConfig(); + + assertTrue(storeConfig.isInMemory()); + assertTrue(isNullOrEmpty(storeConfig.filePath())); + + NitriteCollection test = db.getCollection("test"); + assertNotNull(test); + + db.commit(); + db.close(); + } + + @Test + public void testPopulateRepositories() { + File file = new File(filePath); + MVStoreModule module = MVStoreModule.withConfig().filePath(file).build(); + db = Nitrite.builder() + .fieldSeparator(".") + .loadModule(module) + .openOrCreate(); + + NitriteCollection collection = db.getCollection("test"); + collection.insert(createDocument("id1", "value")); + + ObjectRepository repository = db.getRepository(TestObject.class); + repository.insert(new TestObject("test", 1L)); + + ObjectRepository repository2 = db.getRepository(TestObject.class, "key"); + TestObject object = new TestObject(); + object.stringValue = "test2"; + object.longValue = 2L; + repository2.insert(object); + + ObjectRepository repository3 = db.getRepository(TestObject2.class, "key"); + TestObject2 object2 = new TestObject2(); + object2.stringValue = "test2"; + object2.longValue = 2L; + repository3.insert(object2); + + db.commit(); + db.close(); + + db = Nitrite.builder() + .loadModule(module) + .fieldSeparator(".") + .openOrCreate(); + assertTrue(db.hasCollection("test")); + assertTrue(db.hasRepository(TestObject.class)); + assertTrue(db.hasRepository(TestObject.class, "key")); + assertFalse(db.hasRepository(TestObject2.class)); + assertTrue(db.hasRepository(TestObject2.class, "key")); + } + + + @Test + public void testNitriteMapper() { + NitriteBuilder builder = Nitrite.builder(); + builder.loadModule(module(new CustomNitriteMapper())); + NitriteConfig config = builder.getNitriteConfig(); + assertNotNull(config.nitriteMapper()); + } + + @Test(expected = NitriteSecurityException.class) + public void testOpenOrCreateNullUserId() { + NitriteBuilder builder = Nitrite.builder(); + builder.openOrCreate(null, "abcd"); + } + + @Test(expected = NitriteSecurityException.class) + public void testOpenOrCreateNullPassword() { + NitriteBuilder builder = Nitrite.builder(); + builder.openOrCreate("abcd", null); + } + + @Test(expected = NitriteIOException.class) + public void testDbCorruption() throws IOException { + File file = new File(fakeFile); + FileWriter writesToFile; + // Create file writer object + writesToFile = new FileWriter(file); + // Wrap the writer with buffered streams + BufferedWriter writer = new BufferedWriter(writesToFile); + int line; + Random rand = new Random(); + for (int j = 0; j < 10; j++) { + // Randomize an integer and write it to the output file + line = rand.nextInt(50000); + writer.write(line + "\n"); + } + // Close the stream + writer.close(); + + fakeDb = createDb(fakeFile); + assertNull(fakeDb); + } + + @Test(expected = InvalidOperationException.class) + public void testDbInMemoryReadonly() { + MVStoreModule module = MVStoreModule.withConfig() + .readOnly(true) + .build(); + + fakeDb = Nitrite.builder() + .loadModule(module) + .openOrCreate(); + assertNull(fakeDb); + } + + @Test(expected = NitriteIOException.class) + public void testDbInvalidDirectory() { + fakeFile = System.getProperty("java.io.tmpdir") + File.separator + "fake" + File.separator + "fake.db"; + db = createDb(fakeFile, "test", "test"); + assertNull(db); + } + + @Test + public void testFieldSeparator() { + MVStoreModule module = MVStoreModule.withConfig() + .filePath(filePath) + .build(); + db = Nitrite.builder() + .loadModule(module) + .fieldSeparator("::") + .openOrCreate(); + + Document document = createDocument("firstName", "John") + .put("colorCodes", new Document[]{createDocument("color", "Red"), createDocument("color", "Green")}) + .put("address", createDocument("street", "ABCD Road")); + + String street = document.get("address::street", String.class); + assertEquals("ABCD Road", street); + + // use default separator, it should return null + street = document.get("address.street", String.class); + assertNull(street); + + assertEquals(document.get("colorCodes::1::color"), "Green"); + } + + @Test(expected = NitriteIOException.class) + public void testInvalidPath() { + MVStoreModule module = MVStoreModule.withConfig() + .filePath("http://www.localhost.com") + .build(); + + db = Nitrite.builder() + .loadModule(module) + .openOrCreate("test", "test"); + assertNull(db); + } + + private static class CustomIndexer implements NitriteIndexer { + + @Override + public String getIndexType() { + return "Custom"; + } + + @Override + public void validateIndex(Fields fields) { + + } + + @Override + public void dropIndex(IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig) { + + } + + @Override + public void writeIndexEntry(FieldValues fieldValues, IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig) { + + } + + @Override + public void removeIndexEntry(FieldValues fieldValues, IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig) { + + } + + @Override + public LinkedHashSet findByFilter(FindPlan findPlan, NitriteConfig nitriteConfig) { + return null; + } + + @Override + public void initialize(NitriteConfig nitriteConfig) { + + } + } + + public static class CustomNitriteMapper implements NitriteMapper { + + @Override + public Target convert(Source source, Class type) { + return null; + } + + @Override + public boolean isValueType(Class type) { + return false; + } + + @Override + public boolean isValue(Object object) { + return false; + } + + @Override + public void initialize(NitriteConfig nitriteConfig) { + + } + } + + @Index(value = "longValue") + private static class TestObject implements Mappable { + private String stringValue; + private Long longValue; + + public TestObject() { + } + + public TestObject(String stringValue, Long longValue) { + this.longValue = longValue; + this.stringValue = stringValue; + } + + @Override + public Document write(NitriteMapper mapper) { + return createDocument("stringValue", stringValue) + .put("longValue", longValue); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + if (document != null) { + this.stringValue = document.get("stringValue", String.class); + this.longValue = document.get("longValue", Long.class); + } + } + } + + @Index(value = "longValue") + private static class TestObject2 implements Mappable { + private String stringValue; + private Long longValue; + + public TestObject2() { + } + + public TestObject2(String stringValue, Long longValue) { + this.longValue = longValue; + this.stringValue = stringValue; + } + + @Override + public Document write(NitriteMapper mapper) { + return createDocument("stringValue", stringValue) + .put("longValue", longValue); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + if (document != null) { + this.stringValue = document.get("stringValue", String.class); + this.longValue = document.get("longValue", Long.class); + } + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/NitriteCorruptedTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/NitriteCorruptedTest.java new file mode 100644 index 000000000..72e18a326 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/NitriteCorruptedTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.concurrent.ThreadPoolManager; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.util.concurrent.ExecutorService; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.Filter.ALL; +import static org.dizitart.no2.integration.TestUtil.createDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee + */ +public class NitriteCorruptedTest { + private Nitrite db; + private NitriteCollection collection; + private final String fileName = getRandomTempDbFile(); + private Thread thread; + private final ExecutorService dbPool = ThreadPoolManager.getThreadPool(Runtime.getRuntime().availableProcessors(), + "NitriteCorruptedTest"); + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + db = createDb(fileName); + + collection = db.getCollection("test"); + collection.remove(ALL); + + thread = new Thread(() -> { + for (int i = 0; i < 50000; i++) { + + // Interruption Guard + if (Thread.interrupted()) { + break; + } + + Document doc1 = createDocument(String.valueOf(System.currentTimeMillis()), "fn1") + .put("lastName", "ln1") + .put("data", new byte[]{1, 2, 3}) + .put("body", "a quick brown fox jump over the lazy dog"); + + // Separate user thread from Db write thread + dbPool.submit(() -> collection.insert(doc1)); + } + }); + } + + @After + public void tearDown() throws Exception { + if (collection.isOpen()) { + collection.remove(ALL); + collection.close(); + } + if (db != null && !db.isClosed()) { + db.close(); + } + TestUtil.deleteDb(fileName); + } + + @Test(timeout = 10000) + public void issue118() throws InterruptedException { + try { + thread.start(); + Thread.sleep(10); + thread.interrupt(); + Thread.sleep(500); + assertTrue(collection.isOpen()); + assertFalse(db.isClosed()); + } catch (InterruptedException e) { + if (db != null && !db.isClosed()) { + db.close(); + } + throw e; + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/NitriteSecurityNegativeTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/NitriteSecurityNegativeTest.java new file mode 100644 index 000000000..222038b62 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/NitriteSecurityNegativeTest.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.apache.commons.io.FileUtils; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.exceptions.NitriteException; +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; + +import java.io.File; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.integration.TestUtil.createDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee. + */ +public class NitriteSecurityNegativeTest { + private Nitrite db; + private final String fileName = getRandomTempDbFile(); + + @Rule + public Retry retry = new Retry(3); + + @Test(expected = NitriteException.class) + public void testOpenSecuredWithoutCredential() { + db = createDb(fileName, "test-user", "test-password"); + NitriteCollection dbCollection = db.getCollection("test"); + dbCollection.insert(createDocument("test", "test")); + db.commit(); + db.close(); + + db = createDb(fileName); + dbCollection = db.getCollection("test"); + assertEquals(dbCollection.find().size(), 1); + } + + @Test(expected = NitriteException.class) + public void testOpenUnsecuredWithCredential() { + db = createDb(fileName); + NitriteCollection dbCollection = db.getCollection("test"); + dbCollection.insert(createDocument("test", "test")); + db.commit(); + db.close(); + + db = createDb(fileName, "test-user", "test-password"); + dbCollection = db.getCollection("test"); + assertEquals(dbCollection.find().size(), 1); + } + + @Test(expected = NitriteException.class) + public void testWrongCredential() { + db = createDb(fileName, "test-user", "test-password"); + NitriteCollection dbCollection = db.getCollection("test"); + dbCollection.insert(createDocument("test", "test")); + db.commit(); + db.close(); + + db = createDb(fileName, "test-user", "test-password2"); + dbCollection = db.getCollection("test"); + assertEquals(dbCollection.find().size(), 1); + } + + @After + public void cleanUp() { + if (db != null && !db.isClosed()) { + db.close(); + } + + FileUtils.deleteQuietly(new File(fileName)); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/NitriteSecurityTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/NitriteSecurityTest.java new file mode 100644 index 000000000..a21a9c541 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/NitriteSecurityTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.apache.commons.io.FileUtils; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.exceptions.NitriteSecurityException; +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; + +import java.io.File; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.integration.TestUtil.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * @author Anindya Chatterjee. + */ +public class NitriteSecurityTest { + private Nitrite db; + private final String fileName = getRandomTempDbFile(); + + @Rule + public Retry retry = new Retry(3); + + @Test + public void testSecured() { + db = createDb(fileName, "test-user", "test-password"); + NitriteCollection dbCollection = db.getCollection("test"); + dbCollection.insert(createDocument("test", "test")); + db.commit(); + db.close(); + + db = createDb(fileName, "test-user", "test-password"); + dbCollection = db.getCollection("test"); + assertEquals(dbCollection.find().size(), 1); + db.close(); + deleteDb(fileName); + } + + @Test + public void testUnsecured() { + db = createDb(fileName); + NitriteCollection dbCollection = db.getCollection("test"); + dbCollection.insert(createDocument("test", "test")); + db.commit(); + db.close(); + + db = createDb(fileName); + dbCollection = db.getCollection("test"); + assertEquals(dbCollection.find().size(), 1); + db.close(); + deleteDb(fileName); + } + + @Test + public void testInMemory() { + db = createDb("test-user", "test-password"); + NitriteCollection dbCollection = db.getCollection("test"); + dbCollection.insert(createDocument("test", "test")); + db.commit(); + assertEquals(dbCollection.find().size(), 1); + db.close(); + + db = createDb(); + dbCollection = db.getCollection("test"); + assertEquals(dbCollection.find().size(), 0); + db.close(); + } + + @Test + public void testIssue116() { + db = createDb(fileName, "test-user", "test-password"); + db.close(); + try { + db = createDb(fileName,"test-user2", "test-password2"); + } catch (NitriteSecurityException se) { + db = createDb(fileName,"test-user", "test-password"); + assertNotNull(db); + } finally { + db.close(); + deleteDb(fileName); + } + } + + @After + public void cleanUp() { + if (db != null && !db.isClosed()) { + db.close(); + } + + FileUtils.deleteQuietly(new File(fileName)); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/NitriteStressTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/NitriteStressTest.java new file mode 100644 index 000000000..90b15b3a1 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/NitriteStressTest.java @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import lombok.Data; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; +import org.dizitart.no2.repository.annotations.Indices; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import uk.co.jemos.podam.api.PodamFactory; +import uk.co.jemos.podam.api.PodamFactoryImpl; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.atomic.AtomicLong; + +import static org.dizitart.no2.integration.TestUtil.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + + +/** + * @author Anindya Chatterjee + */ +public class NitriteStressTest { + private static final int TEST_SET_COUNT = 15000; + private final PodamFactory podamFactory = new PodamFactoryImpl(); + private final String fileName = getRandomTempDbFile(); + private Nitrite db; + private NitriteCollection collection; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void before() { + db = createDb(fileName); + collection = db.getCollection("test"); + System.out.println(fileName); + } + + @After + public void cleanUp() { + if (db != null && !db.isClosed()) { + long start = System.currentTimeMillis(); + db.close(); + System.out.println("Time to compact and close - " + (System.currentTimeMillis() - start) / 1000 + " seconds"); + } + + deleteDb(fileName); + } + + @Test + public void stressTest() { + ObjectRepository testRepository = db.getRepository(TestDto.class); + testRepository.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "lastName"); + testRepository.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "birthDate"); + + int counter = 0; + try { + for (TestDto testDto : createTestSet()) { + testRepository.insert(testDto); + counter++; + } + } catch (Throwable t) { + System.err.println("Crashed after " + counter + " records"); + throw t; + } + + int size = testRepository.find().toList().size(); + assertEquals(counter, size); + } + + @Test + public void testIssue41() { + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "number"); + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "name"); + collection.createIndex("counter"); + + Random random = new Random(); + AtomicLong counter = new AtomicLong(System.currentTimeMillis()); + PodamFactory factory = new PodamFactoryImpl(); + + long start = System.currentTimeMillis(); + for (int i = 0; i < 100000; i++) { + Document doc = Document.createDocument(); + doc.put("number", random.nextDouble()); + doc.put("name", factory.manufacturePojo(String.class)); + doc.put("counter", counter.getAndIncrement()); + collection.insert(doc); + if (i % 10000 == 0) { + System.out.println(i + " entries written"); + } + } + System.out.println("Records inserted in " + ((System.currentTimeMillis() - start) / (1000 * 60)) + " minutes"); + + if (db.hasUnsavedChanges()) { + db.commit(); + } + + start = System.currentTimeMillis(); + DocumentCursor cursor = collection.find(); + System.out.println("Size ->" + cursor.size()); + System.out.println("Records size calculated in " + ((System.currentTimeMillis() - start) / (1000)) + " seconds"); + + int i = 0; + start = System.currentTimeMillis(); + for (Document element : cursor) { + assertNotNull(element); + i++; + if (i % 10000 == 0) { + System.out.println(i + " entries processed"); + } + } + System.out.println("Iteration completed in " + ((System.currentTimeMillis() - start) / (1000)) + " seconds"); + } + + @Test + public void testRepoPerformanceWithIndex() { + // warm-up + List items = getItems(PerfTestIndexed.class); + ObjectRepository repo = db.getRepository(PerfTestIndexed.class); + for (PerfTestIndexed item : items) { + assertNotNull(item); + repo.insert(item); + } + repo.remove(Filter.ALL); + repo.drop(); + + // actual calculation + repo = db.getRepository(PerfTestIndexed.class); + long start = System.currentTimeMillis(); + for (PerfTestIndexed item : items) { + repo.insert(item); + } + long diff = System.currentTimeMillis() - start; + System.out.println("Time take to insert 10000 indexed items - " + diff + "ms"); + + start = System.currentTimeMillis(); + repo.remove(Filter.ALL); + diff = System.currentTimeMillis() - start; + System.out.println("Time take to remove 10000 indexed items - " + diff + "ms"); + } + + @Test + public void testRepoPerformanceWithoutIndex() { + // warm-up + List items = getItems(PerfTest.class); + ObjectRepository repo = db.getRepository(PerfTest.class); + for (PerfTest item : items) { + assertNotNull(item); + repo.insert(item); + } + repo.remove(Filter.ALL); + repo.drop(); + + // actual calculation + repo = db.getRepository(PerfTest.class); + long start = System.currentTimeMillis(); + for (PerfTest item : items) { + repo.insert(item); + } + long diff = System.currentTimeMillis() - start; + System.out.println("Time take to insert 10000 non-indexed items - " + diff + "ms"); + + start = System.currentTimeMillis(); + repo.remove(Filter.ALL); + diff = System.currentTimeMillis() - start; + System.out.println("Time take to remove 10000 non-indexed items - " + diff + "ms"); + } + + private List createTestSet() { + List testData = new ArrayList<>(); + for (int i = 0; i < TEST_SET_COUNT; i++) { + TestDto testRecords = podamFactory.manufacturePojo(TestDto.class); + testData.add(testRecords); + } + return testData; + } + + private List getItems(Class type) { + PodamFactory generator = new PodamFactoryImpl(); + List items = new ArrayList<>(); + for (int i = 0; i < 10000; i++) { + items.add(generator.manufacturePojoWithFullData(type)); + } + assertEquals(items.size(), 10000); + return items; + } + + @Data + public static class TestDto implements Mappable { + + @XmlElement( + name = "StudentNumber", + required = true + ) + @Id + protected String studentNumber; + + @XmlElement( + name = "LastName", + required = true + ) + protected String lastName; + + @XmlElement( + name = "Prefixes" + ) + protected String prefixes; + + @XmlElement( + name = "Initials", + required = true + ) + protected String initials; + + @XmlElement( + name = "FirstNames" + ) + protected String firstNames; + @XmlElement( + name = "Nickname" + ) + protected String nickName; + + @XmlElement( + name = "BirthDate", + required = true + ) + @XmlSchemaType( + name = "date" + ) + protected String birthDate; + + + public TestDto() { + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("studentNumber", studentNumber) + .put("lastName", lastName) + .put("prefixes", prefixes) + .put("initials", initials) + .put("firstNames", firstNames) + .put("nickName", nickName) + .put("birthDate", birthDate); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + studentNumber = document.get("studentNumber", String.class); + lastName = document.get("lastName", String.class); + prefixes = document.get("prefixes", String.class); + initials = document.get("initials", String.class); + firstNames = document.get("firstNames", String.class); + nickName = document.get("nickName", String.class); + birthDate = document.get("birthDate", String.class); + } + } + + @Data + public static class PerfTest implements Mappable { + private String firstName; + private String lastName; + private Integer age; + private String text; + + @Override + public Document write(NitriteMapper mapper) { + Document document = Document.createDocument(); + document.put("firstName", firstName); + document.put("lastName", lastName); + document.put("age", age); + document.put("text", text); + return document; + } + + @Override + public void read(NitriteMapper mapper, Document document) { + this.firstName = (String) document.get("firstName"); + this.lastName = (String) document.get("lastName"); + this.age = (Integer) document.get("age"); + this.text = (String) document.get("text"); + } + } + + @Indices({ + @Index(value = "firstName", type = IndexType.NON_UNIQUE), + @Index(value = "age", type = IndexType.NON_UNIQUE), + @Index(value = "text", type = IndexType.FULL_TEXT), + }) + private static class PerfTestIndexed extends PerfTest { + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/Retry.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/Retry.java new file mode 100644 index 000000000..3d6a27d11 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/Retry.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * @author Anindya Chatterjee + */ +public class Retry implements TestRule { + private final int retryCount; + + public Retry(int retryCount) { + this.retryCount = retryCount; + } + + public Statement apply(Statement base, Description description) { + return statement(base, description); + } + + private Statement statement(final Statement base, final Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + Throwable caughtThrowable = null; + + // implement retry logic here + for (int i = 0; i < retryCount; i++) { + try { + base.evaluate(); + return; + } catch (Throwable t) { + caughtThrowable = t; + System.err.println(description.getDisplayName() + ": run " + (i + 1) + " failed"); + } + } + System.err.println(description.getDisplayName() + ": giving up after " + retryCount + " failures"); + throw caughtThrowable; + } + }; + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/SerializabilityTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/SerializabilityTest.java new file mode 100644 index 000000000..09ca50080 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/SerializabilityTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import lombok.Data; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.exceptions.ValidationException; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.File; +import java.io.Serializable; + +/** + * @author Anindya Chatterjee + */ +public class SerializabilityTest { + private NitriteCollection collection; + private File dbFile; + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + dbFile = new File(TestUtil.getRandomTempDbFile()); + db = TestUtil.createDb(dbFile.getPath()); + collection = db.getCollection("test"); + } + + @After + public void tearDown() { + if (db != null && !db.isClosed()) { + db.close(); + } + + if (dbFile.exists()) { + TestUtil.deleteDb(dbFile.getPath()); + } + } + + @Test(expected = ValidationException.class) + public void testSerializabilityValidation() { + for (int i = 0; i < 5; i++) { + Document doc = Document.createDocument(); + doc.put("key", i); + doc.put("data", new NotSerializableClass(Integer.toString(i))); + collection.insert(doc); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("Write " + i + " completed"); + } + } + + @Test + public void testSerializablity() { + for (int i = 0; i < 5; i++) { + Document doc = Document.createDocument(); + doc.put("key", i); + doc.put("data", new SerializableClass(Integer.toString(i))); + collection.insert(doc); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("Write " + i + " completed"); + } + } + + @Data + public static class NotSerializableClass { + private String myId; + + public NotSerializableClass(String myId) { + this.myId = myId; + } + } + + @Data + public static class SerializableClass implements Serializable { + private String myId; + + public SerializableClass(String myId) { + this.myId = myId; + } + } +} + + diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/TestUtil.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/TestUtil.java new file mode 100644 index 000000000..4a0034399 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/TestUtil.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.exceptions.ObjectMappingException; +import org.dizitart.no2.mvstore.MVStoreModule; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; + +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee + */ +@Slf4j +public class TestUtil { + + public static String getRandomTempDbFile() { + String dataDir = System.getProperty("java.io.tmpdir") + File.separator + "nitrite" + File.separator + "data"; + File file = new File(dataDir); + if (!file.exists()) { + assertTrue(file.mkdirs()); + } + return file.getPath() + File.separator + UUID.randomUUID() + ".db"; + } + + @SneakyThrows + public static void deleteDb(String filePath) { + Files.delete(Paths.get(filePath)); + } + + public static > boolean isSorted(Iterable iterable, boolean ascending) { + Iterator iterator = iterable.iterator(); + if (!iterator.hasNext()) { + return true; + } + T t = iterator.next(); + while (iterator.hasNext()) { + T t2 = iterator.next(); + if (ascending) { + if (t.compareTo(t2) > 0) { + return false; + } + } else { + if (t.compareTo(t2) < 0) { + return false; + } + } + t = t2; + } + return true; + } + + public static Nitrite createDb() { + MVStoreModule storeModule = MVStoreModule.withConfig() + .build(); + + return Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .openOrCreate(); + } + + public static Nitrite createDb(String user, String password) { + MVStoreModule storeModule = MVStoreModule.withConfig() + .build(); + + return Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .openOrCreate(user, password); + } + + public static Nitrite createDb(String filePath) { + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(filePath) + .compress(true) + .build(); + + return Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .openOrCreate(); + } + + public static Nitrite createDb(String filePath, String user, String password) { + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(filePath) + .compress(true) + .build(); + + return Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .openOrCreate(user, password); + } + + public static Document parse(String json) { + try { + ObjectMapper objectMapper = createObjectMapper(); + JsonNode node = objectMapper.readValue(json, JsonNode.class); + return loadDocument(node); + } catch (IOException e) { + log.error("Error while parsing json", e); + throw new ObjectMappingException("failed to parse json " + json); + } + } + + private static Document loadDocument(JsonNode node) { + Map objectMap = new LinkedHashMap<>(); + Iterator> fields = node.fields(); + while (fields.hasNext()) { + Map.Entry entry = fields.next(); + String name = entry.getKey(); + JsonNode value = entry.getValue(); + Object object = loadObject(value); + objectMap.put(name, object); + } + + return Document.createDocument(objectMap); + } + + private static Object loadObject(JsonNode node) { + if (node == null) + return null; + try { + switch (node.getNodeType()) { + case ARRAY: + return loadArray(node); + case BINARY: + return node.binaryValue(); + case BOOLEAN: + return node.booleanValue(); + case MISSING: + case NULL: + return null; + case NUMBER: + return node.numberValue(); + case OBJECT: + case POJO: + return loadDocument(node); + case STRING: + return node.textValue(); + } + } catch (IOException e) { + return null; + } + return null; + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private static List loadArray(JsonNode array) { + if (array.isArray()) { + List list = new ArrayList(); + Iterator iterator = array.elements(); + while (iterator.hasNext()) { + Object element = iterator.next(); + if (element instanceof JsonNode) { + list.add(loadObject((JsonNode) element)); + } else { + list.add(element); + } + } + return list; + } + return null; + } + + private static ObjectMapper createObjectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.setVisibility( + objectMapper.getSerializationConfig().getDefaultVisibilityChecker() + .withFieldVisibility(JsonAutoDetect.Visibility.ANY) + .withGetterVisibility(JsonAutoDetect.Visibility.NONE) + .withIsGetterVisibility(JsonAutoDetect.Visibility.NONE)); + objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); + objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); + objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + objectMapper.findAndRegisterModules(); + return objectMapper; + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/BaseCollectionTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/BaseCollectionTest.java new file mode 100644 index 000000000..6898e1169 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/BaseCollectionTest.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import lombok.extern.slf4j.Slf4j; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteBuilder; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.mvstore.MVStoreModule; +import org.dizitart.no2.mvstore.MVStoreModuleBuilder; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Collection; +import java.util.Locale; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.Filter.ALL; +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; + +@Slf4j +@RunWith(value = Parameterized.class) +public abstract class BaseCollectionTest { + @Parameterized.Parameter + public boolean inMemory = false; + @Parameterized.Parameter(value = 1) + public boolean isSecured = false; + @Parameterized.Parameter(value = 2) + public boolean isCompressed = false; + @Parameterized.Parameter(value = 3) + public boolean isAutoCommit = false; + + protected Nitrite db; + protected NitriteCollection collection; + protected Document doc1, doc2, doc3; + protected SimpleDateFormat simpleDateFormat; + private final String fileName = getRandomTempDbFile(); + + @Rule + public Retry retry = new Retry(3); + + @Parameterized.Parameters(name = "InMemory = {0}, Secured = {1}, " + + "Compressed = {2}, AutoCommit = {3}, AutoCompact = {4}") + public static Collection data() { + return Arrays.asList(new Object[][]{ + {false, false, false, false}, + {false, false, false, true}, + {false, false, true, false}, + {false, false, true, true}, + {false, true, false, false}, + {false, true, false, true}, + {false, true, true, false}, + {false, true, true, true}, + {true, false, false, false}, + {true, false, false, true}, + {true, false, true, false}, + {true, false, true, true}, + {true, true, false, false}, + {true, true, false, true}, + {true, true, true, false}, + {true, true, true, true}, + }); + } + + @Before + public void setUp() { + try { + openDb(); + + simpleDateFormat + = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); + + doc1 = createDocument("firstName", "fn1") + .put("lastName", "ln1") + .put("birthDay", simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + .put("data", new byte[]{1, 2, 3}) + .put("list", Arrays.asList("one", "two", "three")) + .put("body", "a quick brown fox jump over the lazy dog"); + doc2 = createDocument("firstName", "fn2") + .put("lastName", "ln2") + .put("birthDay", simpleDateFormat.parse("2010-06-12T16:02:48.440Z")) + .put("data", new byte[]{3, 4, 3}) + .put("list", Arrays.asList("three", "four", "three")) + .put("body", "quick hello world from nitrite"); + doc3 = createDocument("firstName", "fn3") + .put("lastName", "ln2") + .put("birthDay", simpleDateFormat.parse("2014-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + + collection = db.getCollection("test"); + collection.remove(ALL); + } catch (Throwable t) { + log.error("Error while initializing test database", t); + } + } + + @After + public void clear() { + try { + if (collection != null && !collection.isDropped()) { + collection.close(); + } + if (db != null && !db.isClosed()) db.close(); + if (!inMemory) { + deleteDb(fileName); + } + } catch (Throwable t) { + log.error("Error while clearing test database", t); + } + } + + private void openDb() { + MVStoreModuleBuilder builder = MVStoreModule.withConfig(); + + if (isCompressed) { + builder.compress(true); + } + + if (!isAutoCommit) { + builder.autoCommit(false); + } + + if (!inMemory) { + builder.filePath(fileName); + } + + MVStoreModule storeModule = builder.build(); + NitriteBuilder nitriteBuilder = Nitrite.builder() + .fieldSeparator(".") + .loadModule(storeModule); + + if (isSecured) { + db = nitriteBuilder.openOrCreate("test-user", "test-password"); + } else { + db = nitriteBuilder.openOrCreate(); + } + } + + protected WriteResult insert() { + return collection.insert(doc1, doc2, doc3); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexNegativeTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexNegativeTest.java new file mode 100644 index 000000000..746fe397b --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexNegativeTest.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.exceptions.UniqueConstraintException; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Date; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee + */ +public class CollectionCompoundIndexNegativeTest extends BaseCollectionTest { + + @Test(expected = UniqueConstraintException.class) + public void testCreateInvalidUniqueIndex() { + doc1 = createDocument("firstName", "fn3") + .put("lastName", "ln2") + .put("birthDay", new Date()) + .put("data", new byte[]{1, 2, 3}) + .put("list", Arrays.asList("one", "two", "three")) + .put("body", "a quick brown fox jump over the lazy dog"); + + collection.createIndex("lastName", "firstName"); + insert(); + } + + @Test(expected = UniqueConstraintException.class) + public void testCreateUniqueMultiKeyIndexOnArray() { + collection.createIndex("data", "lastName"); + insert(); + } + + @Test(expected = UniqueConstraintException.class) + public void testCreateOnInvalidField() { + insert(); + // multiple null value will be created + collection.createIndex( "my-value", "lastName"); + } + + @Test(expected = IndexingException.class) + public void testDropIndexOnNonIndexedField() { + collection.dropIndex("data", "firstName"); + } + + @Test(expected = IndexingException.class) + public void testRebuildIndexInvalid() { + collection.rebuildIndex("unknown", "firstName"); + } + + @Test(expected = IndexingException.class) + public void createMultipleIndexTypeOnSameFields() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "lastName", "firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName", "firstName"); + } + + @Test(expected = IndexingException.class) + public void testIndexAlreadyExists() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName", "lastName"); + assertTrue(collection.hasIndex("firstName")); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "firstName", "lastName"); + } + + @Test(expected = IndexingException.class) + public void testCreateCompoundTextIndex() { + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body", "lastName"); + } + + @Test(expected = IndexingException.class) + public void testCreateMultiKeyIndexSecondField() { + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName", "data"); + assertTrue(collection.hasIndex("lastName")); + + insert(); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexTest.java new file mode 100644 index 000000000..8d37792ed --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexTest.java @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import com.google.common.collect.Lists; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import java.util.Date; +import java.util.Random; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.awaitility.Awaitility.await; +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.Filter.and; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class CollectionCompoundIndexTest extends BaseCollectionTest { + @Test + public void testCreateAndCheckIndex() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName", "lastName"); + assertTrue(collection.hasIndex("firstName")); + assertTrue(collection.hasIndex("firstName", "lastName")); + assertFalse(collection.hasIndex("firstName", "lastName", "birthDay")); + assertFalse(collection.hasIndex("lastName")); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + insert(); + } + + @Test + public void testCreateMultiKeyIndexFirstField() { + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "data", "lastName"); + assertTrue(collection.hasIndex("data")); + assertTrue(collection.hasIndex("data", "lastName")); + assertFalse(collection.hasIndex("lastName")); + + insert(); + } + + @Test + public void testListIndexes() { + assertEquals(collection.listIndices().size(), 0); + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName", "lastName"); + assertEquals(collection.listIndices().size(), 1); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "firstName"); + assertEquals(collection.listIndices().size(), 2); + } + + @Test + public void testDropIndex() { + collection.createIndex("firstName", "lastName"); + assertTrue(collection.hasIndex("firstName", "lastName")); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.dropIndex("firstName"); + assertTrue(collection.hasIndex("firstName", "lastName")); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex("firstName"); + collection.dropIndex("firstName", "lastName"); + assertFalse(collection.hasIndex("firstName", "lastName")); + assertTrue(collection.hasIndex("firstName")); + + collection.dropIndex("firstName"); + assertFalse(collection.hasIndex("firstName")); + assertEquals(collection.listIndices().size(), 0); + } + + @Test + public void testHasIndex() { + assertFalse(collection.hasIndex("lastName")); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName", "firstName"); + assertTrue(collection.hasIndex("lastName")); + } + + @Test + public void testDropAllIndexes() { + collection.dropAllIndices(); + + collection.createIndex("firstName", "lastName"); + collection.createIndex("firstName"); + assertEquals(collection.listIndices().size(), 2); + + collection.dropAllIndices(); + assertEquals(collection.listIndices().size(), 0); + } + + @Test + public void testRebuildIndex() { + collection.createIndex("firstName", "lastName"); + assertTrue(collection.hasIndex("firstName", "lastName")); + assertTrue(collection.hasIndex("firstName")); + + insert(); + collection.rebuildIndex("firstName", "lastName"); + assertTrue(collection.hasIndex("firstName", "lastName")); + assertTrue(collection.hasIndex("firstName")); + } + + @Test + public void testDeleteWithIndex() { + collection.createIndex("firstName", "lastName"); + + insert(); + + WriteResult result = collection.remove(and(where("firstName").eq("fn1"), + where("lastName").eq("ln1"))); + assertEquals(result.getAffectedCount(), 1); + + result = collection.remove(and(where("firstName").eq("fn2"), + where("birthDay").gte(new Date()))); + assertEquals(result.getAffectedCount(), 0); + } + + @Test + public void testRebuildIndexOnRunningIndex() { + insert(); + db.getStore().subscribe(System.out::println); + + collection.createIndex("firstName", "lastName"); + collection.rebuildIndex("firstName", "lastName"); + + assertTrue(collection.hasIndex("firstName", "lastName")); + } + + @Test + public void testNullValuesInIndexedFields() { + collection.createIndex("firstName", "lastName"); + collection.createIndex("birthDay", "lastName"); + Document document = createDocument("firstName", null) + .put("lastName", "ln1") + .put("birthDay", new Date()) + .put("data", new byte[]{1, 2, 3}) + .put("list", Lists.newArrayList("one", "two", "three")) + .put("body", "a quick brown fox jump over the lazy dog"); + + insert(); + collection.insert(document); + + DocumentCursor cursor = collection.find(where("fistName").eq(null)); + assertEquals("ln1", cursor.firstOrNull().get("lastName", String.class)); + assertNull(cursor.firstOrNull().get("fistName", String.class)); + + document = createDocument("firstName", "fn4") + .put("lastName", null) + .put("birthDay", null) + .put("data", new byte[]{1, 2, 3}) + .put("list", Lists.newArrayList("one", "two", "three")) + .put("body", "a quick brown fox jump over the lazy dog"); + collection.insert(document); + + cursor = collection.find(where("lastName").eq(null)); + assertEquals("fn4", cursor.firstOrNull().get("firstName", String.class)); + assertNull(cursor.firstOrNull().get("fistName", String.class)); + + cursor = collection.find(and(where("lastName").eq(null), where("birthDay").eq(null))); + assertNull(cursor.firstOrNull().get("lastName", String.class)); + } + + @Test + public void testDropAllAndCreateIndex() { + collection.createIndex("firstName", "lastName"); + assertTrue(collection.hasIndex("firstName")); + + DocumentCursor cursor = collection.find(and(where("firstName").eq("fn1"), + where("lastName").eq("ln1"))); + FindPlan findPlan = cursor.getFindPlan(); + assertNotNull(findPlan.getIndexScanFilter()); + assertNull(findPlan.getCollectionScanFilter()); + + collection.dropAllIndices(); + cursor = collection.find(and(where("firstName").eq("fn1"), + where("lastName").eq("ln1"))); + findPlan = cursor.getFindPlan(); + assertNull(findPlan.getIndexScanFilter()); + assertNotNull(findPlan.getCollectionScanFilter()); + + collection.createIndex("firstName", "lastName"); + cursor = collection.find(and(where("firstName").eq("fn1"), + where("lastName").eq("ln1"))); + findPlan = cursor.getFindPlan(); + assertNotNull(findPlan.getIndexScanFilter()); + assertNull(findPlan.getCollectionScanFilter()); + } + + @Test + public void testIssue178() { + collection.dropAllIndices(); + collection.remove(Filter.ALL); + + Document doc1 = createDocument("field1", 5); + Document doc2 = createDocument("field1", 4.3).put("field2", 3.5); + Document doc3 = createDocument("field1", 0.03).put("field2", 5); + Document doc4 = createDocument("field1", 4).put("field2", 4.5); + Document doc5 = createDocument("field1", 5.0).put("field2", 5.0); + + collection.insert(doc1, doc2, doc3, doc4, doc5); + + DocumentCursor cursor = collection.find(and(where("field1").eq(0.03), + where("field2").eq(5))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(and(where("field1").eq(5), + where("field2").eq(null))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("field1").eq(5)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("field1").eq(5.0)); + assertEquals(cursor.size(), 1); + + collection.createIndex("field1", "field2"); + cursor = collection.find(and(where("field1").eq(0.03), + where("field2").eq(5))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(and(where("field1").eq(5), + where("field2").eq(null))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("field1").eq(5)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("field1").eq(5.0)); + assertEquals(cursor.size(), 1); + } + + @Test + public void testIndexEvent() { + NitriteCollection collection = db.getCollection("index-test"); + Random random = new Random(); + for (int i = 0; i < 10000; i++) { + Document document = createDocument("first", random.nextInt()) + .put("second", random.nextDouble()); + collection.insert(document); + } + + AtomicBoolean failed = new AtomicBoolean(false); + AtomicBoolean completed = new AtomicBoolean(false); + collection.subscribe(eventInfo -> { + switch (eventInfo.getEventType()) { + case Insert: + case Remove: + case Update: + failed.set(true); + break; + case IndexStart: + case IndexEnd: + completed.set(true); + break; + } + }); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "first", "second"); + assertEquals(collection.find().size(), 10000); + + await().until(completed::get); + assertFalse(failed.get()); + } + + @Test + public void testIndexAndSearchOnNullValues() { + NitriteCollection collection = db.getCollection("index-on-null"); + collection.insert(createDocument("first", null).put("second", 123).put("third", new Integer[]{1, 2, null})); + collection.insert(createDocument("first", "abcd").put("second", 456).put("third", new int[]{3, 1})); + collection.insert(createDocument("first", "xyz").put("second", 789).put("third", null)); + + collection.createIndex("third", "first"); + assertEquals(collection.find(where("first").eq(null)).size(), 1); + + assertEquals(collection.find(where("third").eq(null)).size(), 2); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionDeleteNegativeTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionDeleteNegativeTest.java new file mode 100644 index 000000000..9c9d9bd6a --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionDeleteNegativeTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.exceptions.NitriteIOException; +import org.dizitart.no2.exceptions.ValidationException; +import org.junit.Test; + +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionDeleteNegativeTest extends BaseCollectionTest { + @Test(expected = NitriteIOException.class) + public void testDrop() { + collection.drop(); + insert(); + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + } + + @Test(expected = FilterException.class) + public void testDeleteWithInvalidFilter() { + insert(); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + + WriteResult writeResult = collection.remove(where("lastName").gt(null)); + assertEquals(writeResult.getAffectedCount(), 0); + } + + @Test(expected = ValidationException.class) + public void testDeleteNullDocument() { + insert(); + + collection.remove((Document) null); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionDeleteTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionDeleteTest.java new file mode 100644 index 000000000..ca1660599 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionDeleteTest.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class CollectionDeleteTest extends BaseCollectionTest { + + @Test + public void testDelete() { + insert(); + + WriteResult writeResult = collection.remove(where("lastName").notEq(null)); + assertEquals(writeResult.getAffectedCount(), 3); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 0); + } + + @Test + public void testDeleteWithOptions() { + insert(); + + WriteResult writeResult = collection.remove(where("lastName").notEq(null), true); + assertEquals(writeResult.getAffectedCount(), 1); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 2); + } + + @Test + public void testDeleteWithNonMatchingFilter() { + insert(); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + + WriteResult writeResult = collection.remove(where("lastName").eq("a")); + assertEquals(writeResult.getAffectedCount(), 0); + } + + @Test + public void testDeleteInEmptyCollection() { + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 0); + + WriteResult writeResult = collection.remove(where("lastName").notEq(null)); + assertEquals(writeResult.getAffectedCount(), 0); + } + + @Test + public void testClear() { + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "firstName"); + insert(); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + assertTrue(collection.hasIndex("firstName")); + + boolean uniqueError = false; + try { + collection.insert(doc1); + } catch (Exception e) { + uniqueError = true; + } finally { + assertTrue(uniqueError); + } + + collection.remove(Filter.ALL); + + cursor = collection.find(); + assertEquals(cursor.size(), 0); + assertTrue(collection.hasIndex("firstName")); + + collection.insert(doc1); + cursor = collection.find(); + assertEquals(cursor.size(), 1); + assertTrue(collection.hasIndex("firstName")); + } + + @Test + public void testRemoveAll() { + insert(); + WriteResult writeResult = collection.remove((Filter) null); + assertEquals(writeResult.getAffectedCount(), 3); + } + + @Test + public void testRemoveDocument() { + insert(); + + WriteResult writeResult = collection.remove(where("firstName").eq("fn1")); + assertEquals(writeResult.getAffectedCount(), 1); + assertEquals(collection.size(), 2); + + writeResult = collection.remove(where("firstName").eq("fn2")); + assertEquals(writeResult.getAffectedCount(), 1); + assertEquals(collection.size(), 1); + + assertEquals(collection.find(where("firstName").eq("fn1")).size(), 0); + assertEquals(collection.find(where("firstName").eq("fn2")).size(), 0); + assertEquals(collection.find(where("firstName").eq("fn3")).size(), 1); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFieldIndexTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFieldIndexTest.java new file mode 100644 index 000000000..358e83a39 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFieldIndexTest.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee + */ +public class CollectionFieldIndexTest extends BaseCollectionTest { + @Test + public void testCollection() { + Document doc1 = Document.createDocument("name", "Anindya") + .put("color", new String[]{"red", "green", "blue"}) + .put("books", new Document[]{ + Document.createDocument("name", "Book ABCD") + .put("tag", new String[]{"tag1", "tag2"}), + Document.createDocument("name", "Book EFGH") + .put("tag", new String[]{"tag3", "tag1"}), + Document.createDocument("name", "No Tag") + }); + + Document doc2 = Document.createDocument("name", "Bill") + .put("color", new String[]{"purple", "yellow", "gray"}) + .put("books", new Document[]{ + Document.createDocument("name", "Book abcd") + .put("tag", new String[]{"tag4", "tag5"}), + Document.createDocument("name", "Book wxyz") + .put("tag", new String[]{"tag3", "tag1"}), + Document.createDocument("name", "No Tag 2") + }); + + Document doc3 = Document.createDocument("name", "John") + .put("color", new String[]{"black", "sky", "violet"}) + .put("books", new Document[]{ + Document.createDocument("name", "Book Mnop") + .put("tag", new String[]{"tag6", "tag2"}), + Document.createDocument("name", "Book ghij") + .put("tag", new String[]{"tag3", "tag7"}), + Document.createDocument("name", "No Tag") + }); + + NitriteCollection collection = db.getCollection("test"); + collection.createIndex("color"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "books.tag"); + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "books.name"); + + WriteResult writeResult = collection.insert(doc1, doc2, doc3); + assertEquals(writeResult.getAffectedCount(), 3); + + DocumentCursor documents = collection.find(where("color").eq("red")); + assertTrue(isSimilar(documents.firstOrNull(), doc1, "name", "color", "books")); + + documents = collection.find(where("books.name").text("abcd")); + assertEquals(documents.size(), 2); + + documents = collection.find(where("books.tag").eq("tag2")); + assertEquals(documents.size(), 2); + + documents = collection.find(where("books.tag").eq("tag5")); + assertEquals(documents.size(), 1); + + documents = collection.find(where("books.tag").eq("tag10")); + assertEquals(documents.size(), 0); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindByCompoundIndexTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindByCompoundIndexTest.java new file mode 100644 index 000000000..8fd30693e --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindByCompoundIndexTest.java @@ -0,0 +1,503 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.filters.AndFilter; +import org.dizitart.no2.filters.IndexScanFilter; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import java.text.ParseException; +import java.util.List; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.collection.FindOptions.orderBy; +import static org.dizitart.no2.filters.Filter.and; +import static org.dizitart.no2.filters.Filter.or; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class CollectionFindByCompoundIndexTest extends BaseCollectionTest { + + @Test + public void testFindByAndFilter() { + insert(); + collection.createIndex("list", "lastName", "firstName"); + DocumentCursor cursor = collection.find(and( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1"), + where("list").eq("four") + )); + + FindPlan findPlan = cursor.getFindPlan(); + assertNull(findPlan.getCollectionScanFilter()); + assertNotNull(findPlan.getIndexDescriptor()); + assertEquals(findPlan.getIndexDescriptor(), collection.listIndices().toArray()[0]); + + IndexScanFilter indexScanFilter = findPlan.getIndexScanFilter(); + assertEquals(indexScanFilter.getFilters().get(0), where("list").eq("four")); + assertEquals(indexScanFilter.getFilters().get(1), where("lastName").eq("ln2")); + assertEquals(indexScanFilter.getFilters().get(2), where("firstName").notEq("fn1")); + + List documents = cursor.toList(); + assertEquals(documents.size(), 1); + assertEquals(documents.get(0).get("body", String.class), "quick hello world from nitrite"); + } + + @Test + public void testFindByOrFilterAndFilter() { + insert(); + collection.createIndex("lastName", "firstName"); + DocumentCursor cursor = collection.find( + or( + and( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + ), + and( + where("firstName").eq("fn3"), + where("lastName").eq("ln2") + ) + ) + ); + + assertEquals(2, cursor.size()); + + FindPlan findPlan = cursor.getFindPlan(); + assertNull(findPlan.getIndexScanFilter()); + assertNull(findPlan.getCollectionScanFilter()); + assertNotNull(findPlan.getSubPlans()); + + assertEquals(2, findPlan.getSubPlans().size()); + assertNotNull(findPlan.getSubPlans().get(0).getIndexScanFilter()); + assertNotNull(findPlan.getSubPlans().get(1).getIndexScanFilter()); + + assertEquals(1, cursor.toList().stream().filter(d -> + d.get("firstName", String.class).equals("fn2") + && d.get("lastName", String.class).equals("ln2")).count()); + + assertEquals(1, cursor.toList().stream().filter(d -> + d.get("firstName", String.class).equals("fn3") + && d.get("lastName", String.class).equals("ln2")).count()); + } + + @Test + public void testFindByAndFilterOrFilter() { + insert(); + collection.createIndex("lastName", "firstName"); + DocumentCursor cursor = collection.find( + and( + or( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + ), + or( + where("firstName").eq("fn3"), + where("lastName").eq("ln2") + ) + ) + ); + + assertEquals(2, cursor.size()); + + FindPlan findPlan = cursor.getFindPlan(); + assertNull(findPlan.getIndexScanFilter()); + assertNotNull(findPlan.getCollectionScanFilter()); + assertTrue(findPlan.getSubPlans().isEmpty()); + + assertEquals(and( + or( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + ), + or( + where("firstName").eq("fn3"), + where("lastName").eq("ln2") + ) + ), findPlan.getCollectionScanFilter()); + } + + @Test + public void testFindByAndFilterAndFilter() { + insert(); + collection.createIndex("lastName", "firstName"); + DocumentCursor cursor = collection.find( + and( + and( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + ), + and( + where("firstName").eq("fn3"), + where("lastName").eq("ln2") + ) + ) + ); + + assertEquals(1, cursor.size()); + FindPlan findPlan = cursor.getFindPlan(); + + assertNotNull(findPlan.getIndexDescriptor()); + assertEquals(collection.listIndices().toArray()[0], findPlan.getIndexDescriptor()); + + assertNotNull(findPlan.getIndexScanFilter()); + assertEquals(findPlan.getIndexScanFilter().getFilters(), + ((AndFilter) and( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + )).getFilters()); + + assertNotNull(findPlan.getCollectionScanFilter()); + assertEquals(where("firstName").eq("fn3"), findPlan.getCollectionScanFilter()); + + assertTrue(findPlan.getSubPlans().isEmpty()); + + assertEquals(cursor.toList().get(0).get("firstName", String.class), "fn3"); + } + + @Test + public void testFindByOrFilter() throws ParseException { + // all or clause has index + insert(); + collection.createIndex("lastName", "firstName"); + collection.createIndex("firstName"); + collection.createIndex("birthDay"); + DocumentCursor cursor = collection.find( + or( + or( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + ), + where("birthDay").eq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")), + where("firstName").notEq("fn1") + ) + ); + + FindPlan findPlan = cursor.getFindPlan(); + assertEquals(3, findPlan.getSubPlans().size()); + assertEquals(3, cursor.size()); + } + + @Test + public void testFindOrNoIndex() throws ParseException { + // on of the or clause has no index + insert(); + collection.createIndex("lastName", "firstName"); + collection.createIndex("firstName"); + DocumentCursor cursor = collection.find( + or( + or( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + ), + where("birthDay").eq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")), + where("firstName").notEq("fn1") + ) + ); + + FindPlan findPlan = cursor.getFindPlan(); + assertEquals(0, findPlan.getSubPlans().size()); + assertEquals(3, cursor.size()); + } + + @Test + public void testFindAndNoIndex() throws ParseException { + // index at second field + insert(); + collection.createIndex("lastName", "firstName"); + DocumentCursor cursor = collection.find( + and( + where("firstName").notEq("fn1"), + where("birthDay").eq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + ) + ); + + FindPlan findPlan = cursor.getFindPlan(); + assertNull(findPlan.getIndexScanFilter()); + assertNull(findPlan.getIndexDescriptor()); + + assertNotNull(findPlan.getCollectionScanFilter()); + assertEquals(0, cursor.size()); + } + + @Test + public void testSortByIndex() throws ParseException { + // multiple field sort in both direction + collection.createIndex("lastName", "birthDay"); + + Document doc = createDocument("firstName", "fn4") + .put("lastName", "ln3") + .put("birthDay", simpleDateFormat.parse("2016-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + collection.insert(doc); + collection.insert(doc3); + collection.insert(doc1); + collection.insert(doc2); + + DocumentCursor cursor = collection.find( + and( + where("lastName").notEq("ln1"), + where("birthDay").notEq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + ), + orderBy("lastName", SortOrder.Ascending) + .thenOrderBy("birthDay", SortOrder.Descending) + ); + + List documents = cursor.toList(); + assertEquals(3, documents.size()); + + Document document = documents.get(0); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2014-04-17T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(1); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2010-06-12T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(2); + assertEquals("ln3", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2016-04-17T16:02:48.440Z"), document.get("birthDay")); + + FindPlan findPlan = cursor.getFindPlan(); + assertTrue(findPlan.getBlockingSortOrder().isEmpty()); + assertNull(findPlan.getCollectionScanFilter()); + assertNotNull(findPlan.getIndexDescriptor()); + assertFalse(findPlan.getIndexScanOrder().get("lastName")); + + // reverse scan + assertTrue(findPlan.getIndexScanOrder().get("birthDay")); + } + + @Test + public void testBlockingSort() throws ParseException { + // multiple field sort in memory + + Document doc = createDocument("firstName", "fn4") + .put("lastName", "ln3") + .put("birthDay", simpleDateFormat.parse("2016-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + collection.insert(doc); + collection.insert(doc3); + collection.insert(doc1); + collection.insert(doc2); + + DocumentCursor cursor = collection.find( + and( + where("lastName").notEq("ln1"), + where("birthDay").notEq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + ), + orderBy("lastName", SortOrder.Ascending) + .thenOrderBy("birthDay", SortOrder.Descending) + ); + + List documents = cursor.toList(); + assertEquals(3, documents.size()); + + Document document = documents.get(0); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2014-04-17T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(1); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2010-06-12T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(2); + assertEquals("ln3", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2016-04-17T16:02:48.440Z"), document.get("birthDay")); + + FindPlan findPlan = cursor.getFindPlan(); + List> blockingSortOrder = findPlan.getBlockingSortOrder(); + assertEquals(2, blockingSortOrder.size()); + + Pair pair = blockingSortOrder.get(0); + assertEquals("lastName", pair.getFirst()); + assertEquals(SortOrder.Ascending, pair.getSecond()); + + pair = blockingSortOrder.get(1); + assertEquals("birthDay", pair.getFirst()); + assertEquals(SortOrder.Descending, pair.getSecond()); + + assertNotNull(findPlan.getCollectionScanFilter()); + assertNull(findPlan.getIndexDescriptor()); + assertNull(findPlan.getIndexScanOrder()); + } + + @Test + public void testSortNotCoveredByIndex() throws ParseException { + // some field sort by index, some by memory + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + + Document doc = createDocument("firstName", "fn4") + .put("lastName", "ln3") + .put("birthDay", simpleDateFormat.parse("2016-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + collection.insert(doc); + collection.insert(doc3); + collection.insert(doc1); + collection.insert(doc2); + + DocumentCursor cursor = collection.find( + and( + where("lastName").notEq("ln1"), + where("birthDay").notEq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + ), + orderBy("lastName", SortOrder.Ascending) + .thenOrderBy("birthDay", SortOrder.Descending) + ); + + List documents = cursor.toList(); + assertEquals(3, documents.size()); + + Document document = documents.get(0); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2014-04-17T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(1); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2010-06-12T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(2); + assertEquals("ln3", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2016-04-17T16:02:48.440Z"), document.get("birthDay")); + + FindPlan findPlan = cursor.getFindPlan(); + List> blockingSortOrder = findPlan.getBlockingSortOrder(); + assertEquals(2, blockingSortOrder.size()); + + Pair pair = blockingSortOrder.get(0); + assertEquals("lastName", pair.getFirst()); + assertEquals(SortOrder.Ascending, pair.getSecond()); + + pair = blockingSortOrder.get(1); + assertEquals("birthDay", pair.getFirst()); + assertEquals(SortOrder.Descending, pair.getSecond()); + + assertNotNull(findPlan.getCollectionScanFilter()); + assertNotNull(findPlan.getIndexDescriptor()); + assertNull(findPlan.getIndexScanOrder()); + } + + @Test + public void testSortByIndexPrefix() throws ParseException { + collection.createIndex("lastName", "birthDay"); + + Document doc = createDocument("firstName", "fn4") + .put("lastName", "ln3") + .put("birthDay", simpleDateFormat.parse("2016-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + collection.insert(doc); + collection.insert(doc3); + collection.insert(doc1); + collection.insert(doc2); + + DocumentCursor cursor = collection.find( + and( + where("lastName").notEq("ln1"), + where("birthDay").notEq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + ), + orderBy("lastName", SortOrder.Ascending) + ); + + List documents = cursor.toList(); + assertEquals(3, documents.size()); + + Document document = documents.get(0); + assertEquals("ln2", document.get("lastName")); + // duplicate birthday will have natural sort order - ascending + assertEquals(simpleDateFormat.parse("2010-06-12T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(1); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2014-04-17T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(2); + assertEquals("ln3", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2016-04-17T16:02:48.440Z"), document.get("birthDay")); + + FindPlan findPlan = cursor.getFindPlan(); + assertTrue(findPlan.getBlockingSortOrder().isEmpty()); + assertNull(findPlan.getCollectionScanFilter()); + assertNotNull(findPlan.getIndexDescriptor()); + assertFalse(findPlan.getIndexScanOrder().get("lastName")); + } + + @Test + public void testLimitAndSkip() throws ParseException { + // test skip and limit + + collection.createIndex("lastName", "birthDay"); + + Document doc = createDocument("firstName", "fn4") + .put("lastName", "ln3") + .put("birthDay", simpleDateFormat.parse("2016-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + collection.insert(doc); + collection.insert(doc3); + collection.insert(doc1); + collection.insert(doc2); + + DocumentCursor cursor = collection.find( + and( + where("lastName").notEq("ln1"), + where("birthDay").notEq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + ), + orderBy("lastName", SortOrder.Ascending) + .thenOrderBy("birthDay", SortOrder.Descending) + .skip(2) + .limit(1) + ); + + List documents = cursor.toList(); + assertEquals(1, documents.size()); + + Document document = documents.get(0); + assertEquals("ln3", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2016-04-17T16:02:48.440Z"), document.get("birthDay")); + + FindPlan findPlan = cursor.getFindPlan(); + assertTrue(findPlan.getBlockingSortOrder().isEmpty()); + assertNull(findPlan.getCollectionScanFilter()); + assertNotNull(findPlan.getIndexDescriptor()); + assertFalse(findPlan.getIndexScanOrder().get("lastName")); + assertEquals(2L, (long)findPlan.getSkip()); + assertEquals(1L, (long)findPlan.getLimit()); + + // reverse scan + assertTrue(findPlan.getIndexScanOrder().get("birthDay")); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindByIndexNegativeTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindByIndexNegativeTest.java new file mode 100644 index 000000000..76b84a0e6 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindByIndexNegativeTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionFindByIndexNegativeTest extends BaseCollectionTest { + @Test(expected = FilterException.class) + public void testFindTextWithWildCardMultipleWord() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + + DocumentCursor cursor = collection.find(where("body").text("*ipsum dolor*")); + assertEquals(cursor.size(), 1); + } + + @Test(expected = FilterException.class) + public void testFindTextWithOnlyWildCard() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + + DocumentCursor cursor = collection.find(where("body").text("*")); + assertEquals(cursor.size(), 1); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindBySingleFieldIndexTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindBySingleFieldIndexTest.java new file mode 100644 index 000000000..cbef67e26 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindBySingleFieldIndexTest.java @@ -0,0 +1,423 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import com.github.javafaker.Faker; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import static org.dizitart.no2.integration.TestUtil.isSorted; +import static org.dizitart.no2.collection.FindOptions.orderBy; +import static org.dizitart.no2.filters.Filter.and; +import static org.dizitart.no2.filters.Filter.or; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionFindBySingleFieldIndexTest extends BaseCollectionTest { + + @Test + public void testFindByUniqueIndex() throws ParseException { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "firstName"); + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("firstName").eq("fn10")); + assertEquals(cursor.size(), 0); + + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "birthDay"); + cursor = collection.find(where("birthDay").gt( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").gte( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lt( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").lte( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lte( + new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").lt( + new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").gt( + new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("birthDay").gte( + new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find( + where("birthDay").lte(new Date()) + .and(where("firstName").eq("fn1"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + where("birthDay").lte(new Date()) + .or(where("firstName").eq("fn12"))); + assertEquals(cursor.size(), 3); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + )); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + ).not()); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").eq((byte) 4)); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").lt(4)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("firstName").notIn("fn1", "fn2")); + assertEquals(cursor.size(), 1); + } + + @Test + public void testFindByNonUniqueIndex() throws ParseException { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "lastName"); + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "birthDay"); + + DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("lastName").eq("ln20")); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("birthDay").gt( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").gte( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lt( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").lte( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lte( + new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").lt( + new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").gt( + new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("birthDay").gte( + new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find( + where("birthDay").lte(new Date()) + .and(where("firstName").eq("fn1"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + where("birthDay").lte(new Date()) + .or(where("firstName").eq("fn12"))); + assertEquals(cursor.size(), 3); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + )); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + ).not()); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").eq((byte) 4)); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").lt(4)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("firstName").notIn("fn1", "fn2")); + assertEquals(cursor.size(), 1); + } + + @Test + public void testFindByFullTextIndexAfterInsert() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + + DocumentCursor cursor = collection.find(where("body").text("Lorem")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("body").text("nosql")); + assertEquals(cursor.size(), 0); + + collection.dropIndex("body"); + boolean filterException = false; + try { + collection.find(where("body").text("Lorem")).toList(); + } catch (FilterException fe) { + filterException = true; + } finally { + assertTrue(filterException); + } + } + + @Test + public void testFindByFullTextIndexBeforeInsert() { + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + insert(); + + DocumentCursor cursor = collection.find(where("body").text("Lorem")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("body").text("quick brown")); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("body").text("nosql")); + assertEquals(cursor.size(), 0); + + collection.dropIndex("body"); + boolean filterException = false; + try { + collection.find(where("body").text("Lorem")).toList(); + } catch (FilterException fe) { + filterException = true; + } finally { + assertTrue(filterException); + } + } + + @Test + public void testFindByIndexSortAscending() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "birthDay"); + + DocumentCursor cursor = collection.find(orderBy("birthDay", SortOrder.Ascending)); + assertEquals(cursor.size(), 3); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, true)); + } + + @Test + public void testFindByIndexSortDescending() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "birthDay"); + + DocumentCursor cursor = collection.find(orderBy("birthDay", SortOrder.Descending)); + assertEquals(cursor.size(), 3); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, false)); + } + + @Test + public void testFindByIndexLimitAndSort() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "birthDay"); + + DocumentCursor cursor = collection.find( + orderBy("birthDay", SortOrder.Descending) + .skip(1) + .limit(2) + ); + assertEquals(cursor.size(), 2); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, false)); + + cursor = collection.find(orderBy("birthDay", SortOrder.Ascending).skip(1).limit(2)); + assertEquals(cursor.size(), 2); + dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, true)); + + cursor = collection.find(orderBy("firstName", SortOrder.Ascending).skip(0).limit(30)); + assertEquals(cursor.size(), 3); + List nameList = new ArrayList<>(); + for (Document document : cursor) { + nameList.add(document.get("firstName", String.class)); + } + assertTrue(isSorted(nameList, true)); + } + + @Test + public void testFindAfterDroppedIndex() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "firstName"); + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + + collection.dropIndex("firstName"); + cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + } + + @Test + public void testFindTextWithWildCard() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + + DocumentCursor cursor = collection.find(where("body").text("Lo")); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("body").text("Lo*")); + assertEquals(cursor.size(), 1); // Lorem + + cursor = collection.find(where("body").text("*rem")); + assertEquals(cursor.size(), 1); // lorem + + cursor = collection.find(where("body").text("*or*")); + assertEquals(cursor.size(), 2); + } + + @Test + public void testFindTextWithEmptyString() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + + DocumentCursor cursor = collection.find(where("body").text("")); + assertEquals(cursor.size(), 0); + } + + @Test + public void testFindWithOrIndexed() { + NitriteCollection collection = db.getCollection("testFindWithOrIndexed"); + Document doc1 = Document.createDocument("firstName", "John").put("lastName", "Doe"); + Document doc2 = Document.createDocument("firstName", "Jane").put("lastName", "Doe"); + Document doc3 = Document.createDocument("firstName", "Jonas").put("lastName", "Doe"); + Document doc4 = Document.createDocument("firstName", "Johan").put("lastName", "Day"); + + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "firstName"); + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "lastName"); + + collection.insert(doc1, doc2, doc3, doc4); + + DocumentCursor cursor = collection.find(where("firstName").eq("John").or(where("lastName").eq("Day"))); + assertEquals(cursor.size(), 2); + + List list = cursor.toList(); + assertEquals(list.size(), 2); + } + + @Test + public void testIssue45() { + NitriteCollection collection = db.getCollection("testIssue45"); + Faker faker = new Faker(); + String text1 = faker.lorem().paragraph() + " quick brown"; + String text2 = faker.lorem().paragraph() + " fox jump"; + String text3 = faker.lorem().paragraph() + " over lazy"; + String text4 = faker.lorem().paragraph() + " dog"; + + List list1 = Arrays.asList(text1, text2); + List list2 = Arrays.asList(text1, text2, text3); + List list3 = Arrays.asList(text2, text3); + List list4 = Arrays.asList(text1, text2, text3, text4); + + Document doc1 = Document.createDocument("firstName", "John").put("notes", list1); + Document doc2 = Document.createDocument("firstName", "Jane").put("notes", list2); + Document doc3 = Document.createDocument("firstName", "Jonas").put("notes", list3); + Document doc4 = Document.createDocument("firstName", "Johan").put("notes", list4); + + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "notes"); + collection.insert(doc1, doc2, doc3, doc4); + + DocumentCursor cursor = collection.find(where("notes").text("fox")); + assertEquals(cursor.size(), 4); + + cursor = collection.find(where("notes").text("dog")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("notes").text("lazy")); + assertEquals(cursor.size(), 3); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindNegativeTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindNegativeTest.java new file mode 100644 index 000000000..8d446cf0f --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindNegativeTest.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.exceptions.ValidationException; +import org.junit.Test; + +import java.util.Date; +import java.util.List; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.collection.FindOptions.orderBy; +import static org.dizitart.no2.collection.FindOptions.skipBy; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionFindNegativeTest extends BaseCollectionTest { + @Test(expected = ValidationException.class) + public void testFindFilterInvalidIndex() { + insert(); + collection.find(where("data.9").eq(4)).toList(); + } + + @Test(expected = ValidationException.class) + public void testFindOptionsNegativeOffset() { + insert(); + collection.find(skipBy(-1).limit(1)); + } + + @Test(expected = ValidationException.class) + public void testFindOptionsNegativeSize() { + insert(); + collection.find(skipBy(0).limit(-1)); + } + + @Test + public void testFindOptionsInvalidOffset() { + insert(); + assertEquals(collection.find(skipBy(10).limit(1)).size(), 0); + } + + @Test(expected = ValidationException.class) + public void testFindInvalidSort() { + insert(); + collection.find(orderBy("data", SortOrder.Descending)).toList(); + } + + @Test(expected = FilterException.class) + public void testFindTextFilterNonIndexed() { + insert(); + collection.find(where("body").text("Lorem")).toList(); + } + + @Test(expected = FilterException.class) + public void testFindWithRegexInvalidValue() { + insert(); + DocumentCursor cursor = collection.find(where("birthDay").regex("hello")); + assertEquals(cursor.size(), 1); + } + + @Test(expected = ValidationException.class) + public void testInvalidProjection() { + insert(); + DocumentCursor cursor = collection.find(where("birthDay").lte(new Date()), + orderBy("firstName", SortOrder.Ascending).skip(0).limit(3)); + + Document projection = createDocument("firstName", null) + .put("lastName", "ln2"); + + cursor.project(projection); + } + + @Test(expected = UnsupportedOperationException.class) + public void testToListAdd() { + insert(); + DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); + List documents = cursor.toList(); + documents.add(createDocument()); + } + + @Test(expected = UnsupportedOperationException.class) + public void testToListRemove() { + insert(); + DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); + List documents = cursor.toList(); + documents.clear(); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindTest.java new file mode 100644 index 000000000..f5e5a2c04 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindTest.java @@ -0,0 +1,825 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.joda.time.DateTime; +import org.junit.Test; + +import java.text.Collator; +import java.text.ParseException; +import java.util.*; +import java.util.stream.Collectors; + +import static org.dizitart.no2.integration.TestUtil.isSorted; +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.collection.FindOptions.*; +import static org.dizitart.no2.common.Constants.*; +import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; +import static org.dizitart.no2.filters.Filter.*; +import static org.dizitart.no2.filters.FluentFilter.$; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.*; + +public class CollectionFindTest extends BaseCollectionTest { + + private static Document trimMeta(Document document) { + document.remove(DOC_ID); + document.remove(DOC_REVISION); + document.remove(DOC_MODIFIED); + document.remove(DOC_SOURCE); + return document; + } + + @Test + public void testFindAll() { + insert(); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + } + + @Test + public void testFindWithFilter() throws ParseException { + insert(); + + DocumentCursor cursor = collection.find(where("birthDay").gt( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").gte( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lt( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").lte( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lte( + new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").lt( + new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").gt( + new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("birthDay").gte( + new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find( + where("birthDay").lte(new Date()) + .and(where("firstName").eq("fn1"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + where("birthDay").lte(new Date()) + .or(where("firstName").eq("fn12"))); + assertEquals(cursor.size(), 3); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + )); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + ).not()); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").eq((byte) 4)); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").lt(4)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("firstName").notIn("fn1", "fn2")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(ALL.not()); + assertEquals(cursor.size(), 0); + } + + @Test + public void testFindWithSkipLimit() { + insert(); + + DocumentCursor cursor = collection.find(skipBy(0).limit(1)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(skipBy(1).limit(3)); + assertEquals(cursor.size(), 2); + + cursor = collection.find(skipBy(0).limit(30)); + assertEquals(cursor.size(), 3); + + cursor = collection.find(skipBy(2).limit(3)); + assertEquals(cursor.size(), 1); + } + + @Test + public void testFindWithSkip() { + insert(); + + DocumentCursor cursor = collection.find(skipBy(0)); + assertEquals(cursor.size(), 3); + + cursor = collection.find(skipBy(1)); + assertEquals(cursor.size(), 2); + + cursor = collection.find(skipBy(30)); + assertEquals(cursor.size(), 0); + + cursor = collection.find(skipBy(2)); + assertEquals(cursor.size(), 1); + + boolean invalid = false; + try { + cursor = collection.find(skipBy(-1)); + assertEquals(cursor.size(), 1); + } catch (ValidationException e) { + invalid = true; + } + assertTrue(invalid); + } + + @Test + public void testFindWithLimit() { + insert(); + + DocumentCursor cursor = collection.find(limitBy(0)); + assertEquals(cursor.size(), 0); + + cursor = collection.find(limitBy(1)); + assertEquals(cursor.size(), 1); + + boolean invalid = false; + try { + cursor = collection.find(limitBy(-1)); + assertEquals(cursor.size(), 1); + } catch (ValidationException e) { + invalid = true; + } + assertTrue(invalid); + + cursor = collection.find(limitBy(30)); + assertEquals(cursor.size(), 3); + } + + @Test + public void testFindSortAscending() { + insert(); + + DocumentCursor cursor = collection.find(orderBy("birthDay", SortOrder.Ascending)); + assertEquals(cursor.size(), 3); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, true)); + } + + @Test + public void testFindSortDescending() { + insert(); + + DocumentCursor cursor = collection.find(orderBy("birthDay", SortOrder.Descending)); + assertEquals(cursor.size(), 3); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, false)); + } + + @Test + public void testFindLimitAndSort() { + insert(); + + DocumentCursor cursor = collection.find(orderBy("birthDay", SortOrder.Descending).skip(1).limit(2)); + assertEquals(cursor.size(), 2); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, false)); + + cursor = collection.find(orderBy("birthDay", SortOrder.Ascending).skip(1).limit(2)); + assertEquals(cursor.size(), 2); + dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, true)); + + cursor = collection.find(orderBy("firstName", SortOrder.Ascending).skip(0).limit(30)); + assertEquals(cursor.size(), 3); + List nameList = new ArrayList<>(); + for (Document document : cursor) { + nameList.add(document.get("firstName", String.class)); + } + assertTrue(isSorted(nameList, true)); + } + + @Test + public void testFindSortOnNonExistingField() { + insert(); + DocumentCursor cursor = collection.find(orderBy("my-value", SortOrder.Descending)); + assertEquals(cursor.size(), 3); + } + + @Test + public void testFindInvalidField() { + insert(); + DocumentCursor cursor = collection.find(where("myField").eq("myData")); + assertEquals(cursor.size(), 0); + } + + @Test + public void testFindInvalidFieldWithInvalidAccessor() { + insert(); + DocumentCursor cursor = collection.find(where("myField.0").eq("myData")); + assertEquals(cursor.size(), 0); + } + + @Test + public void testFindLimitAndSortInvalidField() { + insert(); + DocumentCursor cursor = collection.find(orderBy("birthDay2", SortOrder.Descending).skip(1).limit(2)); + assertEquals(cursor.size(), 2); + } + + @Test + public void testGetById() { + collection.insert(doc1); + NitriteId id = NitriteId.createId("1"); + Document document = collection.getById(id); + assertNull(document); + + document = collection.find().firstOrNull(); + + assertEquals(document.get(DOC_ID), document.getId().getIdValue()); + assertEquals(document.get("firstName"), "fn1"); + assertEquals(document.get("lastName"), "ln1"); + assertArrayEquals((byte[]) document.get("data"), new byte[]{1, 2, 3}); + assertEquals(document.get("body"), "a quick brown fox jump over the lazy dog"); + } + + @Test + public void testFindWithFilterAndOption() { + insert(); + DocumentCursor cursor = collection.find(where("birthDay").lte(new Date()), + orderBy("firstName", SortOrder.Ascending).skip(1).limit(2)); + assertEquals(cursor.size(), 2); + } + + @Test + public void testFindTextWithRegex() { + insert(); + DocumentCursor cursor = collection.find(where("body").regex("hello")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("body").regex("test")); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("body").regex("^hello$")); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("body").regex(".*")); + assertEquals(cursor.size(), 3); + } + + @Test + public void testProject() { + insert(); + DocumentCursor cursor = collection.find(where("birthDay").lte(new Date()), + orderBy("firstName", SortOrder.Ascending).skip(0).limit(3)); + int iteration = 0; + for (Document document : cursor) { + switch (iteration) { + case 0: + assertTrue(isSimilar(document, doc1, "firstName", "lastName", "birthDay", "data", "list", "body")); + break; + case 1: + assertTrue(isSimilar(document, doc2, "firstName", "lastName", "birthDay", "data", "list", "body")); + break; + case 2: + assertTrue(isSimilar(document, doc3, "firstName", "lastName", "birthDay", "data", "list", "body")); + break; + } + iteration++; + } + assertEquals(iteration, 3); + } + + @Test + public void testProjectWithCustomDocument() { + insert(); + DocumentCursor cursor = collection.find(where("birthDay").lte(new Date()), + orderBy("firstName", SortOrder.Ascending).skip(0).limit(3)); + + Document projection = createDocument("firstName", null) + .put("lastName", null); + + Iterable documents = cursor.project(projection); + int iteration = 0; + for (Document document : documents) { + assertTrue(document.containsKey("firstName")); + assertTrue(document.containsKey("lastName")); + + assertFalse(document.containsKey("_id")); + assertFalse(document.containsKey("birthDay")); + assertFalse(document.containsKey("data")); + assertFalse(document.containsKey("body")); + + switch (iteration) { + case 0: + assertEquals(document.get("firstName"), "fn1"); + assertEquals(document.get("lastName"), "ln1"); + break; + case 1: + assertEquals(document.get("firstName"), "fn2"); + assertEquals(document.get("lastName"), "ln2"); + break; + case 2: + assertEquals(document.get("firstName"), "fn3"); + assertEquals(document.get("lastName"), "ln2"); + break; + } + iteration++; + } + assertEquals(iteration, 3); + } + + @Test + public void testFindWithArrayEqual() { + insert(); + DocumentCursor ids = collection.find(where("data").eq(new byte[]{3, 4, 3})); + assertNotNull(ids); + assertEquals(ids.size(), 1); + } + + @Test + public void testFindWithArrayEqualFailForWrongCardinality() { + insert(); + DocumentCursor ids = collection.find(where("data").eq(new byte[]{4, 3, 3})); + assertNotNull(ids); + assertEquals(ids.size(), 0); + } + + @Test + public void testFindWithIterableEqual() { + insert(); + DocumentCursor ids = collection.find(where("list").eq( + new ArrayList() {{ + add("three"); + add("four"); + add("three"); + }})); + assertNotNull(ids); + assertEquals(ids.size(), 1); + } + + @Test + public void testFindWithIterableEqualFailForWrongCardinality() { + insert(); + DocumentCursor ids = collection.find(where("list").eq( + new ArrayList() {{ + add("four"); + add("three"); + add("three"); + }})); + assertNotNull(ids); + assertEquals(ids.size(), 0); + } + + @Test + public void testFindInArray() { + insert(); + DocumentCursor ids = collection.find(where("data").elemMatch($.gte(2).and($.lt(5)))); + assertNotNull(ids); + assertEquals(ids.size(), 3); + + ids = collection.find(where("data").elemMatch($.gt(2).or($.lte(5)))); + assertNotNull(ids); + assertEquals(ids.size(), 3); + + ids = collection.find(where("data").elemMatch($.gt(1).and($.lt(4)))); + assertNotNull(ids); + assertEquals(ids.size(), 2); + } + + @Test + public void testFindInList() { + insert(); + DocumentCursor ids = collection.find(where("list").elemMatch($.regex("three"))); + assertNotNull(ids); + assertEquals(ids.size(), 2); + + ids = collection.find(where("list").elemMatch($.regex("hello"))); + assertNotNull(ids); + assertEquals(ids.size(), 0); + + ids = collection.find(where("list").elemMatch($.regex("hello").not())); + assertNotNull(ids); + assertEquals(ids.size(), 2); + } + + @Test + public void testElemMatchFilter() { + Document doc1 = createDocument("productScores", new Document[]{ + createDocument("product", "abc").put("score", 10), + createDocument("product", "xyz").put("score", 5) + }).put("strArray", new String[]{"a", "b"}); + + Document doc2 = createDocument("productScores", new Document[]{ + createDocument("product", "abc").put("score", 8), + createDocument("product", "xyz").put("score", 7) + }).put("strArray", new String[]{"d", "e"}); + + Document doc3 = createDocument("productScores", new Document[]{ + createDocument("product", "abc").put("score", 7), + createDocument("product", "xyz").put("score", 8) + }).put("strArray", new String[]{"a", "f"}); + + NitriteCollection prodCollection = db.getCollection("prodScore"); + prodCollection.insert(doc1, doc2, doc3); + + List documentList = prodCollection.find(where("productScores") + .elemMatch(where("product").eq("xyz").and(where("score").gte(8)))).toList(); + + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").lte(8).not())).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("product").eq("xyz").or(where("score").gte(8)))).toList(); + assertEquals(documentList.size(), 3); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("product").eq("xyz"))).toList(); + assertEquals(documentList.size(), 3); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").gte(10))).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").gt(8))).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").lt(7))).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").lte(7))).toList(); + assertEquals(documentList.size(), 3); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").in(7, 8))).toList(); + assertEquals(documentList.size(), 2); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").notIn(7, 8))).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("product").regex("xyz"))).toList(); + assertEquals(documentList.size(), 3); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.eq("a"))).toList(); + assertEquals(documentList.size(), 2); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.eq("a").or($.eq("f").or($.eq("b"))).not())).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.gt("e"))).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.gte("e"))).toList(); + assertEquals(documentList.size(), 2); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.lte("b"))).toList(); + assertEquals(documentList.size(), 2); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.lt("a"))).toList(); + assertEquals(documentList.size(), 0); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.in("a", "f"))).toList(); + assertEquals(documentList.size(), 2); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.regex("a"))).toList(); + assertEquals(documentList.size(), 2); + + } + + @Test + public void testNotEqualFilter() { + Document document = createDocument("abc", "123"); + document.put("xyz", null); + + collection.insert(document); + DocumentCursor cursor = collection.find(where("abc").eq("123")); + assertEquals(cursor.size(), 1); + assertEquals(cursor.toList().size(), 1); + + cursor = collection.find(where("xyz").eq(null)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("abc").notEq(null)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("abc").notEq(null).and(where("xyz").eq(null))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("abc").eq(null).and(where("xyz").notEq(null))); + assertEquals(cursor.size(), 0); + + collection.remove(ALL); + + document = createDocument("field", "two"); + document.put(DOC_REVISION, 1482225343161L); + + collection.insert(document); + Document projection = collection.find( + where(DOC_REVISION).gte(1482225343160L) + .and(where(DOC_REVISION).lte(1482225343162L) + .and(where(DOC_REVISION).notEq(null)))) + .firstOrNull(); + + assertNull(projection); + } + + @Test + public void testFilterAll() { + DocumentCursor cursor = collection.find(ALL); + assertNotNull(cursor); + assertEquals(cursor.size(), 0); + + insert(); + cursor = collection.find(ALL); + assertNotNull(cursor); + assertEquals(cursor.size(), 3); + } + + @Test + public void testIssue72() { + NitriteCollection coll = db.getCollection("test"); + coll.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "id"); + coll.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "group"); + + coll.remove(ALL); + + Document doc = createDocument().put("id", "test-1").put("group", "groupA"); + assertEquals(1, coll.insert(doc).getAffectedCount()); + + doc = createDocument().put("id", "test-2").put("group", "groupA").put("startTime", DateTime.now()); + assertEquals(1, coll.insert(doc).getAffectedCount()); + + DocumentCursor cursor = coll.find(where("group").eq("groupA"), + orderBy("startTime", SortOrder.Descending)); + assertEquals(2, cursor.size()); + assertNull(cursor.toList().get(1).get("startTime")); + assertNotNull(cursor.toList().get(0).get("startTime")); + + cursor = coll.find(where("group").eq("groupA"), + orderBy("startTime", SortOrder.Ascending)); + assertEquals(2, cursor.size()); + assertNull(cursor.toList().get(0).get("startTime")); + assertNotNull(cursor.toList().get(1).get("startTime")); + } + + @Test + public void testIssue93() { + NitriteCollection coll = db.getCollection("orderByOnNullableColumn2"); + + coll.remove(ALL); + + Document doc = createDocument().put("id", "test-2").put("group", "groupA"); + assertEquals(1, coll.insert(doc).getAffectedCount()); + + doc = createDocument().put("id", "test-1").put("group", "groupA"); + assertEquals(1, coll.insert(doc).getAffectedCount()); + + DocumentCursor cursor = coll.find(where("group").eq("groupA"), + orderBy("startTime", SortOrder.Descending)); + assertEquals(2, cursor.size()); + } + + @Test + public void testNullOrderWithAllNull() { + NitriteCollection coll = db.getCollection("test"); + + coll.remove(ALL); + + Document doc = createDocument().put("id", "test-2").put("group", "groupA"); + assertEquals(1, coll.insert(doc).getAffectedCount()); + + doc = createDocument().put("id", "test-1").put("group", "groupA"); + assertEquals(1, coll.insert(doc).getAffectedCount()); + + DocumentCursor cursor = coll.find(where("group").eq("groupA"), + orderBy("startTime", SortOrder.Descending)); + assertEquals(2, cursor.size()); + } + + @Test + public void testDefaultNullOrder() { + NitriteCollection coll = db.getCollection("test"); + try { + coll.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "startTime"); + } catch (IndexingException e) { + // ignore + } + + coll.remove(ALL); + + Document doc1 = createDocument().put("id", "test-1").put("group", "groupA"); + assertEquals(1, coll.insert(doc1).getAffectedCount()); + + Document doc2 = createDocument().put("id", "test-2").put("group", "groupA").put("startTime", DateTime.now()); + assertEquals(1, coll.insert(doc2).getAffectedCount()); + + Document doc3 = createDocument().put("id", "test-3").put("group", "groupA").put("startTime", DateTime.now().plusMinutes(1)); + assertEquals(1, coll.insert(doc3).getAffectedCount()); + + DocumentCursor cursor = coll.find(where("group").eq("groupA"), + orderBy("startTime", SortOrder.Descending)); + assertEquals(3, cursor.size()); + assertThat(Arrays.asList(doc3, doc2, doc1), + is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); + + + cursor = coll.find(where("group").eq("groupA"), + orderBy("startTime", SortOrder.Ascending)); + assertEquals(3, cursor.size()); + assertThat(Arrays.asList(doc1, doc2, doc3), + is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); + } + + @Test + public void testFindFilterInvalidAccessor() { + insert(); + DocumentCursor cursor = collection.find(where("lastName.name").eq("ln2")); + assertEquals(cursor.size(), 0); + } + + @Test + public void testIssue144() { + Document doc1 = createDocument().put("id", "test-1").put("fruit", "Apple"); + Document doc2 = createDocument().put("id", "test-2").put("fruit", "Ôrange"); + Document doc3 = createDocument().put("id", "test-3").put("fruit", "Pineapple"); + + NitriteCollection coll = db.getCollection("test"); + coll.insert(doc1, doc2, doc3); + + DocumentCursor cursor = coll.find(orderBy("fruit", SortOrder.Ascending) + .collator(Collator.getInstance(Locale.FRANCE))); + assertEquals(cursor.toList().get(1).get("fruit"), "Ôrange"); + } + + @Test + public void testIdSet() { + insert(); + DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("lastName").eq("ln1")); + assertEquals(cursor.size(), 1); + + Document byId = cursor.iterator().next(); + assertEquals(byId.get("lastName"), "ln1"); + } + + @Test + public void testCollectionField() { + Document document = createDocument("name", "John") + .put("tags", new Document[]{ + createDocument("type", "example").put("other", "value"), + createDocument("type", "another-example").put("other", "some-other-value") + }); + + NitriteCollection example = db.getCollection("example"); + example.insert(document); + + document = createDocument("name", "Jane") + .put("tags", new Document[]{ + createDocument("type", "example2").put("other", "value2"), + createDocument("type", "another-example2").put("other", "some-other-value2") + }); + example.insert(document); + + DocumentCursor cursor = example.find(where("tags").elemMatch(where("type").eq("example"))); + for (Document doc : cursor) { + assertNotNull(doc); + assertEquals(doc.get("name"), "John"); + } + } + + @Test + public void testBetweenFilter() { + Document doc1 = createDocument("age", 31).put("tag", "one"); + Document doc2 = createDocument("age", 32).put("tag", "two"); + Document doc3 = createDocument("age", 33).put("tag", "three"); + Document doc4 = createDocument("age", 34).put("tag", "four"); + Document doc5 = createDocument("age", 35).put("tag", "five"); + + NitriteCollection collection = db.getCollection("tag"); + collection.insert(doc1, doc2, doc3, doc4, doc5); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "age"); + + DocumentCursor cursor = collection.find(where("age").between(31, 35)); + assertEquals(cursor.size(), 5); + + cursor = collection.find(where("age").between(31, 35, false)); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("age").between(31, 35, false, true)); + assertEquals(cursor.size(), 4); + + cursor = collection.find(where("age").between(31, 35, false).not()); + assertEquals(cursor.size(), 2); + } + + @Test + public void testByIdFilter() { + Document doc1 = createDocument("age", 31).put("tag", "one"); + Document doc2 = createDocument("age", 32).put("tag", "two"); + Document doc3 = createDocument("age", 33).put("tag", "three"); + Document doc4 = createDocument("age", 34).put("tag", "four"); + Document doc5 = createDocument("age", 35).put("tag", "five"); + + NitriteCollection collection = db.getCollection("tag"); + collection.insert(doc1, doc2, doc3, doc4, doc5); + + List documentList = collection.find().toList(); + Document document = documentList.get(0); + NitriteId nitriteId = document.getId(); + + Document result = collection.find(byId(nitriteId)).firstOrNull(); + assertEquals(document, result); + + result = collection.find(and(byId(nitriteId), where("age").notEq(null))).firstOrNull(); + assertEquals(document, result); + + result = collection.find(or(byId(nitriteId), where("tag").eq(document.get("tag")))).firstOrNull(); + assertEquals(document, result); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionIndexNegativeTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionIndexNegativeTest.java new file mode 100644 index 000000000..f6ce8612e --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionIndexNegativeTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.exceptions.UniqueConstraintException; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionIndexNegativeTest extends BaseCollectionTest { + + @Test(expected = UniqueConstraintException.class) + public void testCreateInvalidUniqueIndex() { + collection.createIndex("lastName"); + assertTrue(collection.hasIndex("lastName")); + insert(); + } + + @Test(expected = UniqueConstraintException.class) + public void testCreateIndexOnArray() { + collection.createIndex("data"); + assertTrue(collection.hasIndex("data")); + // data array field has repetition, so unique constraint exception + insert(); + } + + @Test(expected = UniqueConstraintException.class) + public void testCreateOnInvalidField() { + insert(); + collection.createIndex("my-value"); + assertTrue(collection.hasIndex("my-value")); + } + + @Test(expected = IndexingException.class) + public void testCreateFullTextOnNonTextField() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "birthDay"); + assertTrue(collection.hasIndex("birthDay")); + } + + @Test(expected = IndexingException.class) + public void testDropIndexOnNonIndexedField() { + collection.dropIndex("data"); + } + + @Test(expected = IndexingException.class) + public void testRebuildIndexInvalid() { + collection.rebuildIndex("unknown"); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionIndexTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionIndexTest.java new file mode 100644 index 000000000..247a1705a --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionIndexTest.java @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Random; +import java.util.concurrent.Callable; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionIndexTest extends BaseCollectionTest { + + @Test + public void testCollection() { + Document doc1 = Document.createDocument("name", "Anindya") + .put("color", new String[]{"red", "green", "blue"}) + .put("books", new Document[]{ + Document.createDocument("name", "Book ABCD") + .put("tag", new String[]{"tag1", "tag2"}), + Document.createDocument("name", "Book EFGH") + .put("tag", new String[]{"tag3", "tag1"}), + Document.createDocument("name", "No Tag") + }); + + Document doc2 = Document.createDocument("name", "Bill") + .put("color", new String[]{"purple", "yellow", "gray"}) + .put("books", new Document[]{ + Document.createDocument("name", "Book abcd") + .put("tag", new String[]{"tag4", "tag5"}), + Document.createDocument("name", "Book wxyz") + .put("tag", new String[]{"tag3", "tag1"}), + Document.createDocument("name", "No Tag 2") + }); + + Document doc3 = Document.createDocument("name", "John") + .put("color", new String[]{"black", "sky", "violet"}) + .put("books", new Document[]{ + Document.createDocument("name", "Book Mnop") + .put("tag", new String[]{"tag6", "tag2"}), + Document.createDocument("name", "Book ghij") + .put("tag", new String[]{"tag3", "tag7"}), + Document.createDocument("name", "No Tag") + }); + + NitriteCollection collection = db.getCollection("test"); + collection.createIndex("color"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "books.tag"); + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "books.name"); + + WriteResult writeResult = collection.insert(doc1, doc2, doc3); + assertEquals(writeResult.getAffectedCount(), 3); + + DocumentCursor documents = collection.find(where("color").eq("red")); + assertTrue(isSimilar(documents.firstOrNull(), doc1, "name", "color", "books")); + + documents = collection.find(where("books.name").text("abcd")); + assertEquals(documents.size(), 2); + + documents = collection.find(where("books.tag").eq("tag2")); + assertEquals(documents.size(), 2); + + documents = collection.find(where("books.tag").eq("tag5")); + assertEquals(documents.size(), 1); + + documents = collection.find(where("books.tag").eq("tag10")); + assertEquals(documents.size(), 0); + } + + @Test + public void testCreateIndex() { + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + + collection.createIndex("birthDay", null); + assertTrue(collection.hasIndex("birthDay")); + + insert(); + } + + @Test + public void testListIndexes() { + assertEquals(collection.listIndices().size(), 0); + + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + + assertEquals(collection.listIndices().size(), 3); + } + + @Test + public void testDropIndex() { + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.dropIndex("firstName"); + assertFalse(collection.hasIndex("firstName")); + } + + @Test + public void testDropAllIndexes() { + collection.dropAllIndices(); + + testCreateIndex(); + assertEquals(collection.listIndices().size(), 4); + + collection.dropAllIndices(); + assertEquals(collection.listIndices().size(), 0); + } + + @Test + public void testHasIndex() { + assertFalse(collection.hasIndex("lastName")); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + assertFalse(collection.hasIndex("body")); + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + } + + @Test + public void testDeleteWithIndex() { + collection.createIndex("firstName"); + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + + insert(); + + WriteResult result = collection.remove(where("firstName").eq("fn1")); + assertEquals(result.getAffectedCount(), 1); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 2); + + result = collection.remove(where("body").text("Lorem")); + assertEquals(result.getAffectedCount(), 1); + + cursor = collection.find(); + assertEquals(cursor.size(), 1); + } + + @Test + public void testRebuildIndex() { + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + insert(); + Collection indices = collection.listIndices(); + for (IndexDescriptor idx : indices) { + collection.rebuildIndex(idx.getIndexFields().getFieldNames().toArray(new String[0])); + } + } + + private Callable bodyIndexingCompleted() { + return () -> !collection.isIndexing("body"); + } + + @Test + public void testNullValueInIndexedField() { + collection.createIndex("firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "birthDay"); + insert(); + + Document document = createDocument("firstName", null) + .put("lastName", "ln1") + .put("birthDay", null) + .put("data", new byte[]{1, 2, 3}) + .put("list", new ArrayList() {{ + add("one"); + add("two"); + add("three"); + }}) + .put("body", "a quick brown fox jump over the lazy dog"); + + collection.insert(document); + } + + @Test + public void testDropAllAndCreateIndex() { + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + collection.dropAllIndices(); + assertFalse(collection.hasIndex("firstName")); + + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection = db.getCollection("test"); + assertTrue(collection.hasIndex("firstName")); + } + + @Test + public void testIssue178() { + collection.dropAllIndices(); + collection.remove(Filter.ALL); + + Document doc1 = createDocument("field", 5); + Document doc2 = createDocument("field", 4.3); + Document doc3 = createDocument("field", 0.03); + Document doc4 = createDocument("field", 4); + Document doc5 = createDocument("field", 5.0); + + collection.insert(doc1, doc2, doc3, doc4, doc5); + + DocumentCursor cursor = collection.find(where("field").eq(5)); + assertEquals(cursor.size(), 1); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "field"); + + cursor = collection.find(where("field").eq(5)); + assertEquals(cursor.size(), 1); + } + + @Test + public void testIndexEvent() { + NitriteCollection collection = db.getCollection("index-test"); + Random random = new Random(); + for (int i = 0; i < 10000; i++) { + Document document = createDocument("first", random.nextInt()) + .put("second", random.nextDouble()); + collection.insert(document); + } + + collection.subscribe(eventInfo -> { + switch (eventInfo.getEventType()) { + case Insert: + fail("wrong event Insert"); + break; + case Update: + fail("wrong event Update"); + break; + case Remove: + fail("wrong event Remove"); + break; + case IndexStart: + case IndexEnd: + break; + } + assertTrue(eventInfo.getItem() instanceof String); + System.out.println(eventInfo.getEventType() + " for field " + eventInfo.getItem()); + }); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "first"); + assertEquals(collection.find().size(), 10000); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "second"); + assertEquals(collection.find().size(), 10000); + } + + @Test + public void testIndexAndSearchOnNullValues() { + NitriteCollection collection = db.getCollection("index-on-null"); + collection.insert(createDocument("first", null).put("second", 123).put("third", new Integer[]{1, 2, null})); + collection.insert(createDocument("first", "abcd").put("second", 456).put("third", new int[]{3, 1})); + collection.insert(createDocument("first", "xyz").put("second", 789).put("third", null)); + + collection.createIndex("first"); + assertEquals(collection.find(where("first").eq(null)).size(), 1); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "third"); + assertEquals(collection.find(where("third").eq(null)).size(), 2); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionInsertNegativeTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionInsertNegativeTest.java new file mode 100644 index 000000000..02358caf6 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionInsertNegativeTest.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.exceptions.UniqueConstraintException; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionInsertNegativeTest extends BaseCollectionTest { + @Test(expected = UniqueConstraintException.class) + public void testMultipleInsert() { + WriteResult result = collection.insert(doc1, doc2, doc3); + assertEquals(result.getAffectedCount(), 3); + Document document = collection.find().firstOrNull(); + collection.insert(document); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionInsertTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionInsertTest.java new file mode 100644 index 000000000..cd9558946 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionInsertTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.common.WriteResult; +import org.junit.Test; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.common.Constants.DOC_ID; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class CollectionInsertTest extends BaseCollectionTest { + + @Test + public void testInsert() { + WriteResult result = collection.insert(doc1, doc2, doc3); + assertEquals(result.getAffectedCount(), 3); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + + for (Document document : cursor) { + assertNotNull(document.get("firstName")); + assertNotNull(document.get("lastName")); + assertNotNull(document.get("birthDay")); + assertNotNull(document.get("data")); + assertNotNull(document.get("body")); + assertNotNull(document.get(DOC_ID)); + } + } + + @Test + public void testInsertHeteroDocs() { + Document document = createDocument("test", "Nitrite Test"); + + WriteResult result = collection.insert(doc1, doc2, doc3, document); + assertEquals(result.getAffectedCount(), 4); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionJoinTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionJoinTest.java new file mode 100644 index 000000000..caff44d61 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionJoinTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import lombok.extern.slf4j.Slf4j; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.Lookup; +import org.dizitart.no2.common.RecordStream; +import org.junit.Before; +import org.junit.Test; + +import java.util.Collection; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.Filter.ALL; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +@Slf4j +public class CollectionJoinTest extends BaseCollectionTest { + private NitriteCollection foreignCollection; + + @Before + @Override + public void setUp() { + try { + super.setUp(); + foreignCollection = db.getCollection("foreign"); + foreignCollection.remove(ALL); + + Document fdoc1 = createDocument("fName", "fn1") + .put("address", "ABCD Street") + .put("telephone", "123456789"); + + Document fdoc2 = createDocument("fName", "fn2") + .put("address", "XYZ Street") + .put("telephone", "000000000"); + + Document fdoc3 = createDocument("fName", "fn2") + .put("address", "Some other Street") + .put("telephone", "7893141321"); + + foreignCollection.insert(fdoc1, fdoc2, fdoc3); + } catch (Throwable t) { + log.error("Error while initializing test database", t); + } + } + + @Test + @SuppressWarnings("unchecked") + public void testJoinAll() { + insert(); + + Lookup lookup = new Lookup(); + lookup.setLocalField("firstName"); + lookup.setForeignField("fName"); + lookup.setTargetField("personalDetails"); + + RecordStream result = collection.find().join(foreignCollection.find(), lookup); + assertEquals(result.size(), 3); + + for (Document document : result) { + if (document.get("firstName") == "fn1") { + Collection personalDetails = (Collection) document.get("personalDetails"); + assertNotNull(personalDetails); + assertEquals(personalDetails.size(), 1); + Object[] details = personalDetails.toArray(); + assertEquals(((Document) details[0]).get("telephone"), "123456789"); + } else if (document.get("firstName") == "fn2") { + Collection personalDetails = (Collection) document.get("personalDetails"); + assertNotNull(personalDetails); + assertEquals(personalDetails.size(), 2); + Object[] details = personalDetails.toArray(); + for (Object o : details) { + Document d = (Document) o; + if (d.get("address").equals("XYZ Street")) { + assertEquals(d.get("telephone"), "000000000"); + } else { + assertEquals(d.get("telephone"), "7893141321"); + } + } + } else if (document.get("firstName") == "fn3") { + assertNull(document.get("personalDetails")); + } + System.out.println(document); + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionSingleFieldIndexNegativeTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionSingleFieldIndexNegativeTest.java new file mode 100644 index 000000000..b459e469b --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionSingleFieldIndexNegativeTest.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.exceptions.UniqueConstraintException; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionSingleFieldIndexNegativeTest extends BaseCollectionTest { + + @Test(expected = UniqueConstraintException.class) + public void testCreateInvalidUniqueIndex() { + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + insert(); + } + + @Test(expected = UniqueConstraintException.class) + public void testCreateIndexOnArray() { + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "data"); + assertTrue(collection.hasIndex("data")); + // data array field has repetition, so unique constraint exception + insert(); + } + + @Test(expected = UniqueConstraintException.class) + public void testCreateOnInvalidField() { + insert(); + // multiple null value will be created + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "my-value"); + assertTrue(collection.hasIndex("my-value")); + } + + @Test(expected = IndexingException.class) + public void testCreateFullTextOnNonTextField() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "birthDay"); + assertTrue(collection.hasIndex("birthDay")); + } + + @Test(expected = IndexingException.class) + public void testDropIndexOnNonIndexedField() { + collection.dropIndex("data"); + } + + @Test(expected = IndexingException.class) + public void testRebuildIndexInvalid() { + collection.rebuildIndex("unknown"); + } + + @Test(expected = IndexingException.class) + public void createMultipleIndexTypeOnSameField() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "lastName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionSingleFieldIndexTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionSingleFieldIndexTest.java new file mode 100644 index 000000000..fe37845e1 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionSingleFieldIndexTest.java @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Random; +import java.util.concurrent.Callable; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.awaitility.Awaitility.await; +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionSingleFieldIndexTest extends BaseCollectionTest { + + @Test + public void testCreateIndex() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + + collection.createIndex("birthDay"); + assertTrue(collection.hasIndex("birthDay")); + + insert(); + } + + @Test + public void testListIndexes() { + assertEquals(collection.listIndices().size(), 0); + + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + + assertEquals(collection.listIndices().size(), 3); + } + + @Test + public void testDropIndex() { + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.dropIndex("firstName"); + assertFalse(collection.hasIndex("firstName")); + } + + @Test + public void testDropAllIndexes() { + collection.dropAllIndices(); + + testCreateIndex(); + assertEquals(collection.listIndices().size(), 4); + + collection.dropAllIndices(); + assertEquals(collection.listIndices().size(), 0); + } + + @Test + public void testHasIndex() { + assertFalse(collection.hasIndex("lastName")); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + assertFalse(collection.hasIndex("body")); + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + } + + @Test + public void testDeleteWithIndex() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName"); + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + + insert(); + + WriteResult result = collection.remove(where("firstName").eq("fn1")); + assertEquals(result.getAffectedCount(), 1); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 2); + + result = collection.remove(where("body").text("Lorem")); + assertEquals(result.getAffectedCount(), 1); + + cursor = collection.find(); + assertEquals(cursor.size(), 1); + } + + @Test + public void testRebuildIndex() { + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + insert(); + Collection indices = collection.listIndices(); + for (IndexDescriptor idx : indices) { + collection.rebuildIndex(idx.getIndexFields().getFieldNames().toArray(new String[0])); + } + } + + @Test + public void testRebuildIndexOnRunningIndex() { + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + insert(); + collection.rebuildIndex("body"); + + boolean error = false; + try { + collection.rebuildIndex("body"); + } catch (IndexingException ie) { + error = true; + } finally { + assertFalse(error); + await().until(bodyIndexingCompleted()); + } + } + + private Callable bodyIndexingCompleted() { + return () -> !collection.isIndexing("body"); + } + + @Test + public void testNullValueInIndexedField() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "birthDay"); + insert(); + + Document document = createDocument("firstName", null) + .put("lastName", "ln1") + .put("birthDay", null) + .put("data", new byte[]{1, 2, 3}) + .put("list", new ArrayList() {{ + add("one"); + add("two"); + add("three"); + }}) + .put("body", "a quick brown fox jump over the lazy dog"); + + collection.insert(document); + } + + @Test + public void testDropAllAndCreateIndex() { + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + collection.dropAllIndices(); + assertFalse(collection.hasIndex("firstName")); + + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection = db.getCollection("test"); + assertTrue(collection.hasIndex("firstName")); + } + + @Test + public void testIssue178() { + collection.dropAllIndices(); + collection.remove(Filter.ALL); + + Document doc1 = createDocument("field", 5); + Document doc2 = createDocument("field", 4.3); + Document doc3 = createDocument("field", 0.03); + Document doc4 = createDocument("field", 4); + Document doc5 = createDocument("field", 5.0); + + collection.insert(doc1, doc2, doc3, doc4, doc5); + + DocumentCursor cursor = collection.find(where("field").eq(5)); + assertEquals(cursor.size(), 1); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "field"); + + cursor = collection.find(where("field").eq(5)); + assertEquals(cursor.size(), 1); + } + + @Test + public void testIndexEvent() { + NitriteCollection collection = db.getCollection("index-test"); + Random random = new Random(); + for (int i = 0; i < 10000; i++) { + Document document = createDocument("first", random.nextInt()) + .put("second", random.nextDouble()); + collection.insert(document); + } + + AtomicBoolean failed = new AtomicBoolean(false); + AtomicBoolean completed = new AtomicBoolean(false); + collection.subscribe(eventInfo -> { + switch (eventInfo.getEventType()) { + case Insert: + case Remove: + case Update: + failed.set(true); + break; + case IndexStart: + case IndexEnd: + completed.set(true); + break; + } + }); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "first"); + assertEquals(collection.find().size(), 10000); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "second"); + assertEquals(collection.find().size(), 10000); + + await().until(completed::get); + assertFalse(failed.get()); + } + + @Test + public void testIndexAndSearchOnNullValues() { + NitriteCollection collection = db.getCollection("index-on-null"); + collection.insert(createDocument("first", null).put("second", 123).put("third", new Integer[]{1, 2, null})); + collection.insert(createDocument("first", "abcd").put("second", 456).put("third", new int[]{3, 1})); + collection.insert(createDocument("first", "xyz").put("second", 789).put("third", null)); + + collection.createIndex(indexOptions(IndexType.UNIQUE), "first"); + assertEquals(collection.find(where("first").eq(null)).size(), 1); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "third"); + assertEquals(collection.find(where("third").eq(null)).size(), 2); + } + + @Test + public void testCreateCompoundAndSingleFieldIndexOnSameField() { + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName", "firstName"); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionUpdateTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionUpdateTest.java new file mode 100644 index 000000000..86bff59b5 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionUpdateTest.java @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.UpdateOptions; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.exceptions.NitriteIOException; +import org.dizitart.no2.exceptions.NotIdentifiableException; +import org.dizitart.no2.exceptions.UniqueConstraintException; +import org.dizitart.no2.filters.Filter; +import org.junit.Test; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + +public class CollectionUpdateTest extends BaseCollectionTest { + + @Test + public void testUpdate() { + insert(); + + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + for (Document document : cursor) { + assertEquals(document.get("lastName"), "ln1"); + } + + WriteResult updateResult = collection.update(where("firstName").eq("fn1"), + createDocument("lastName", "new-last-name")); + assertEquals(updateResult.getAffectedCount(), 1); + + cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + for (Document document : cursor) { + assertEquals(document.get("lastName"), "new-last-name"); + } + } + + @Test(expected = NotIdentifiableException.class) + public void testUpsertWithoutId() { + insert(); + Document update = createDocument("lastName", "ln4"); + WriteResult writeResult = collection.update(update, false); + assertEquals(writeResult.getAffectedCount(), 0); + assertEquals(collection.size(), 3); + } + + @Test + public void testUpsert() { + insert(); + assertEquals(collection.size(), 3); + + Document update = createDocument("lastName", "ln4"); + WriteResult writeResult = collection.update(update, true); + assertEquals(writeResult.getAffectedCount(), 1); + assertEquals(collection.size(), 4); + + Document document = collection.find(where("lastName").eq("ln4")) + .firstOrNull(); + assertTrue(isSimilar(document, update, "lastName")); + } + + @Test + public void testOptionUpsert() { + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 0); + + WriteResult updateResult = collection.update(where("firstName").eq("fn1"), + doc1, UpdateOptions.updateOptions(true)); + assertEquals(updateResult.getAffectedCount(), 1); + + cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + for (Document document : cursor) { + assertTrue(isSimilar(document, doc1, "firstName", "lastName", "birthDay", "data", "list", "body")); + } + } + + @Test + public void testUpdateMultiple() { + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 0); + + insert(); + + Document document = createDocument("lastName", "newLastName1"); + WriteResult updateResult = collection.update(where("firstName").eq("fn1").not(), + document); + assertEquals(updateResult.getAffectedCount(), 2); + + cursor = collection.find(where("lastName").eq("newLastName1")); + assertEquals(cursor.size(), 2); + } + + @Test + public void testUpdateWithOptionsUpsertFalse() { + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 0); + + UpdateOptions updateOptions = new UpdateOptions(); + updateOptions.setInsertIfAbsent(false); + + WriteResult updateResult = collection.update(where("firstName").eq("fn1"), + doc1, updateOptions); + assertEquals(updateResult.getAffectedCount(), 0); + + cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 0); + } + + @Test + public void testUpdateMultipleWithJustOnceFalse() { + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 0); + + insert(); + + UpdateOptions updateOptions = new UpdateOptions(); + updateOptions.setJustOnce(false); + + Document document = createDocument("lastName", "newLastName1"); + WriteResult updateResult = collection.update(where("firstName").eq("fn1").not(), + document, updateOptions); + assertEquals(updateResult.getAffectedCount(), 2); + + cursor = collection.find(where("lastName").eq("newLastName1")); + assertEquals(cursor.size(), 2); + } + + @Test + public void testUpdateMultipleWithJustOnceTrue() { + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 0); + + insert(); + + UpdateOptions updateOptions = new UpdateOptions(); + updateOptions.setJustOnce(true); + + Document document = createDocument("lastName", "newLastName1"); + collection.update(where("firstName").eq("fn1").not(), + document, updateOptions); + } + + @Test + public void testUpdateWithNewField() { + insert(); + + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + for (Document document : cursor) { + assertEquals(document.get("lastName"), "ln1"); + } + + WriteResult updateResult = collection.update(where("firstName").eq("fn1"), + createDocument("new-value", "new-value-value")); + assertEquals(updateResult.getAffectedCount(), 1); + + cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + for (Document document : cursor) { + assertEquals(document.get("new-value"), "new-value-value"); + } + } + + @Test + public void testUpdateInvalidFilter() { + insert(); + + DocumentCursor cursor = collection.find(where("lastName").eq("ln1")); + assertEquals(cursor.size(), 1); + for (Document document : cursor) { + assertEquals(document.get("firstName"), "fn1"); + } + + // to check if NitriteId is valid. + WriteResult updateResult = collection.update(where("some-value").eq("some-value"), + createDocument("lastName", "new-last-name")); + assertEquals(updateResult.getAffectedCount(), 0); + } + + @Test + public void updateAfterAttributeRemoval() { + NitriteCollection coll = db.getCollection("test_updateAfterAttributeRemoval"); + coll.remove(Filter.ALL); + + Document doc = createDocument().put("id", "test-1").put("group", "groupA"); + assertEquals(1, coll.insert(doc).getAffectedCount()); + + Document savedDoc1 = coll.find().firstOrNull(); + assertNotNull(savedDoc1); + + Document clonedDoc1 = savedDoc1.clone(); + assertEquals(savedDoc1, clonedDoc1); + + clonedDoc1.put("group", null); +// clonedDoc1.remove("group"); + assertEquals(1, coll.update(clonedDoc1).getAffectedCount()); + + Document savedDoc2 = coll.find(Filter.ALL).firstOrNull(); + assertNotNull(savedDoc2); + assertNull(savedDoc2.get("group")); + } + + @Test(expected = NotIdentifiableException.class) + public void testUpdateWithoutId() { + NitriteCollection collection = db.getCollection("test"); + Document document = createDocument("test", "test123"); + collection.update(document); + } + + @Test(expected = NotIdentifiableException.class) + public void testRemoveWithoutId() { + NitriteCollection collection = db.getCollection("test"); + Document document = createDocument("test", "test123"); + collection.remove(document); + } + + @Test(expected = NitriteIOException.class) + public void testRegisterListenerAfterDrop() { + NitriteCollection collection = db.getCollection("test"); + collection.drop(); + collection.subscribe(changeInfo -> fail("should not happen")); + } + + @Test(expected = NitriteIOException.class) + public void testRegisterListenerAfterClose() throws Exception { + NitriteCollection collection = db.getCollection("test"); + collection.close(); + collection.subscribe(changeInfo -> fail("should not happen")); + } + + @Test(expected = UniqueConstraintException.class) + public void testIssue151() { + Document doc1 = createDocument().put("id", "test-1").put("fruit", "Apple"); + Document doc2 = createDocument().put("id", "test-2").put("fruit", "Ôrange"); + NitriteCollection coll = db.getCollection("test"); + coll.insert(doc1, doc2); + + coll.createIndex("fruit"); + + assertEquals(coll.find(where("fruit").eq("Apple")).size(), 1); + + Document doc3 = coll.find(where("id").eq("test-2")).firstOrNull(); + + doc3.put("fruit", "Apple"); + coll.update(doc3); + + assertEquals(coll.find(where("fruit").eq("Apple")).size(), 1); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/FieldProcessorTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/FieldProcessorTest.java new file mode 100644 index 000000000..0055f97ac --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/FieldProcessorTest.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.common.crypto.AESEncryptor; +import org.dizitart.no2.common.crypto.Encryptor; +import org.dizitart.no2.common.processors.Processor; +import org.dizitart.no2.common.processors.StringFieldEncryptionProcessor; +import org.dizitart.no2.exceptions.NitriteSecurityException; +import org.dizitart.no2.store.NitriteMap; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.nio.charset.StandardCharsets; +import java.util.Date; +import java.util.List; + +import static org.dizitart.no2.common.util.Iterables.toList; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class FieldProcessorTest extends BaseCollectionTest { + + private Encryptor encryptor; + private NitriteCollection collection; + private Processor cvvProcessor; + + @Before + public void setUp() { + super.setUp(); + + encryptor = new AESEncryptor("s3k4e8"); + cvvProcessor = new Processor() { + @Override + public Document processBeforeWrite(Document document) { + String cvv = document.get("cvv", String.class); + String encryptedCvv = encryptor.encrypt(cvv.getBytes(StandardCharsets.UTF_8)); + document.put("cvv", encryptedCvv); + return document; + } + + @Override + public Document processAfterRead(Document document) { + String encryptedCvv = document.get("cvv", String.class); + String cvv = encryptor.decrypt(encryptedCvv); + document.put("cvv", cvv); + return document; + } + }; + StringFieldEncryptionProcessor creditCardProcessor = new StringFieldEncryptionProcessor(encryptor); + creditCardProcessor.addFields("creditCardNumber"); + + collection = db.getCollection("encryption-test"); + collection.addProcessor(creditCardProcessor); + + Document document = Document.createDocument("name", "John Doe") + .put("creditCardNumber", "5548960345687452") + .put("cvv", "007") + .put("expiryDate", new Date()); + collection.insert(document); + + document = Document.createDocument("name", "Jane Doe") + .put("creditCardNumber", "5500960345687452") + .put("cvv", "008") + .put("expiryDate", new Date()); + collection.insert(document); + + collection.addProcessor(cvvProcessor); + } + + @Test + public void testFieldEncryptionInNitriteMap() { + NitriteMap nitriteMap = collection.getStore().openMap("encryption-test", + NitriteId.class, Document.class); + + List documents = toList(nitriteMap.values()); + for (Document document : documents) { + if (document.get("creditCardNumber", String.class).equalsIgnoreCase("5548960345687452")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("creditCardNumber", String.class).equalsIgnoreCase("5500960345687452")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("cvv", String.class).equalsIgnoreCase("008")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("cvv", String.class).equalsIgnoreCase("007")) { + Assert.fail("unencrypted secret text found"); + } + } + } + + @Test + public void testSuccessfulDecryption() { + Document document = collection.find(where("name").eq("Jane Doe")).firstOrNull(); + assertNotNull(document); + + assertEquals(document.get("creditCardNumber", String.class), "5500960345687452"); + assertEquals(document.get("cvv", String.class), "008"); + + document = collection.find(where("name").eq("John Doe")).firstOrNull(); + assertNotNull(document); + + assertEquals(document.get("creditCardNumber", String.class), "5548960345687452"); + assertEquals(document.get("cvv", String.class), "007"); + } + + @Test(expected = NitriteSecurityException.class) + public void testFailedDecryption() { + Encryptor wrongEncryptor = new AESEncryptor("secret"); + + collection = db.getCollection("encryption-test"); + collection.addProcessor(new Processor() { + @Override + public Document processBeforeWrite(Document document) { + String creditCardNumber = document.get("creditCardNumber", String.class); + String encryptedCreditCardNumber = encryptor.encrypt(creditCardNumber.getBytes(StandardCharsets.UTF_8)); + document.put("creditCardNumber", encryptedCreditCardNumber); + return document; + } + + @Override + public Document processAfterRead(Document document) { + String encryptedCreditCardNumber = document.get("creditCardNumber", String.class); + String creditCardNumber = wrongEncryptor.decrypt(encryptedCreditCardNumber); + document.put("creditCardNumber", creditCardNumber); + return document; + } + }); + + Document document = Document.createDocument("name", "John Doe") + .put("creditCardNumber", "5548960345687452") + .put("cvv", "007") + .put("expiryDate", new Date()); + collection.insert(document); + + document = Document.createDocument("name", "Jane Doe") + .put("creditCardNumber", "5500960345687452") + .put("cvv", "008") + .put("expiryDate", new Date()); + collection.insert(document); + + collection.find(where("name").eq("Jane Doe")).firstOrNull(); + } + + @Test + public void testSearchOnEncryptedField() { + Document document = collection.find(where("cvv").eq("008")).firstOrNull(); + assertNull(document); + } + + @Test + public void testUpdateEncryptedField() { + Document document = Document.createDocument("name", "John Doe") + .put("creditCardNumber", "00000000000000") + .put("cvv", "007") + .put("expiryDate", new Date()); + + WriteResult writeResult = collection.update(where("name").eq("John Doe"), document); + assertEquals(writeResult.getAffectedCount(), 1); + + document = collection.find(where("name").eq("John Doe")).firstOrNull(); + assertNotNull(document); + + assertEquals(document.get("creditCardNumber", String.class), "00000000000000"); + assertEquals(document.get("cvv", String.class), "007"); + } + + @Test + public void testIndexOnEncryptedField() { + collection.createIndex("cvv"); + Document document = collection.find(where("cvv").eq("008")).firstOrNull(); + assertNull(document); + } + + @Test + public void testRemoveProcessor() { + Document document = collection.find(where("cvv").eq("008")).firstOrNull(); + assertNull(document); + + collection.removeProcessor(cvvProcessor); + + document = collection.find(where("cvv").eq("008")).firstOrNull(); + assertNotNull(document); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/NitriteCollectionTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/NitriteCollectionTest.java new file mode 100644 index 000000000..ad3534435 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/NitriteCollectionTest.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.meta.Attributes; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee + */ +public class NitriteCollectionTest extends BaseCollectionTest { + + @Test + public void testAttributes() { + NitriteCollection collection = db.getCollection("test"); + + Attributes attributes = new Attributes("test"); + collection.setAttributes(attributes); + + assertEquals(collection.getAttributes(), attributes); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/event/EventTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/event/EventTest.java new file mode 100644 index 000000000..813a36503 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/event/EventTest.java @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.event; + +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.integration.repository.data.Employee; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteBuilder; +import org.dizitart.no2.collection.events.EventType; +import org.dizitart.no2.mvstore.MVStoreModule; +import org.dizitart.no2.mvstore.MVStoreModuleBuilder; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.awaitility.Awaitility.await; +import static org.dizitart.no2.filters.Filter.ALL; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +@RunWith(Parameterized.class) +public class EventTest { + @Parameterized.Parameter + public boolean inMemory = false; + @Parameterized.Parameter(value = 1) + public boolean isProtected = false; + @Parameterized.Parameter(value = 2) + public boolean isCompressed = false; + @Parameterized.Parameter(value = 3) + public boolean isAutoCommit = false; + + private final String fileName = getRandomTempDbFile(); + private Nitrite db; + private ObjectRepository employeeRepository; + private SampleListenerCollection listener; + + @Rule + public Retry retry = new Retry(3); + + @Parameterized.Parameters(name = "InMemory = {0}, Protected = {1}, " + + "Compressed = {2}, AutoCommit = {3}") + public static Collection data() { + return Arrays.asList(new Object[][]{ + {false, false, false, false}, + {false, false, false, true}, + {false, false, true, false}, + {false, false, true, true}, + {false, true, false, false}, + {false, true, false, true}, + {false, true, true, false}, + {false, true, true, true}, + {true, false, false, false}, + {true, false, false, true}, + {true, false, true, false}, + {true, false, true, true}, + {true, true, false, false}, + {true, true, false, true}, + {true, true, true, false}, + {true, true, true, true}, + }); + } + + @Before + public void setUp() { + MVStoreModuleBuilder builder = MVStoreModule.withConfig(); + + if (isCompressed) { + builder.compress(true); + } + + if (!isAutoCommit) { + builder.autoCommit(false); + } + + if (!inMemory) { + builder.filePath(fileName); + } + + MVStoreModule storeModule = builder.build(); + NitriteBuilder nitriteBuilder = Nitrite.builder() + .fieldSeparator(".") + .loadModule(storeModule); + + if (isProtected) { + db = nitriteBuilder.openOrCreate("test-user", "test-password"); + } else { + db = nitriteBuilder.openOrCreate(); + } + + employeeRepository = db.getRepository(Employee.class); + listener = new SampleListenerCollection(); + employeeRepository.subscribe(listener); + } + + @Test + public void testInsert() { + Employee employee = new Employee(); + employee.setEmpId(1L); + employeeRepository.insert(employee); + await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); + assertEquals(listener.getAction(), EventType.Insert); + assertNotNull(listener.getItem()); + } + + @Test + public void testUpdate() { + Employee e = new Employee(); + e.setEmpId(1L); + e.setAddress("abcd"); + employeeRepository.insert(e); + await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); + assertEquals(listener.getAction(), EventType.Insert); + assertNotNull(listener.getItem()); + + e.setAddress("xyz"); + employeeRepository.update(where("empId").eq(1L), e); + await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Update)); + assertEquals(listener.getAction(), EventType.Update); + assertNotNull(listener.getItem()); + + Employee byId = employeeRepository.getById(1L); + assertEquals(byId.getAddress(), "xyz"); + } + + @Test + public void testUpsert() { + Employee e = new Employee(); + e.setEmpId(1L); + e.setAddress("abcd"); + + employeeRepository.update(where("empId").eq(1), e, true); + await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); + assertEquals(listener.getAction(), EventType.Insert); + assertNotNull(listener.getItem()); + } + + @Test + public void testDelete() { + Employee e = new Employee(); + e.setEmpId(1L); + e.setAddress("abcd"); + + employeeRepository.insert(e); + await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); + + employeeRepository.remove(where("empId").eq(1L)); + await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Remove)); + + System.out.println("Action - " + listener.getAction()); + assertEquals(listener.getAction(), EventType.Remove); + assertNotNull(listener.getItem()); + } + + @Test + public void testDrop() { + employeeRepository.drop(); + assertNull(listener.getItem()); + } + + @Test + public void testClose() { + if (employeeRepository.isOpen()) { + employeeRepository.close(); + } + assertNull(listener.getItem()); + } + + @Test + public void testDeregister() { + employeeRepository.unsubscribe(listener); + Employee e = new Employee(); + e.setEmpId(1L); + e.setAddress("abcd"); + + employeeRepository.insert(e); + assertNull(listener.getAction()); + assertNull(listener.getItem()); + } + + @Test + public void testMultipleListeners() { + final AtomicInteger count = new AtomicInteger(0); + employeeRepository.subscribe(changeInfo -> count.incrementAndGet()); + + employeeRepository.subscribe(changeInfo -> count.incrementAndGet()); + + Employee e = new Employee(); + e.setEmpId(1L); + e.setAddress("abcd"); + employeeRepository.insert(e); + + await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); + assertEquals(count.get(), 2); + } + + @Test + public void testSingleEventListener() { + final AtomicInteger count = new AtomicInteger(0); + employeeRepository.subscribe(changeInfo -> count.incrementAndGet()); + + employeeRepository = db.getRepository(Employee.class); + Employee e = new Employee(); + e.setEmpId(1L); + e.setAddress("abcd"); + employeeRepository.insert(e); + + await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); + assertEquals(count.get(), 1); + } + + @After + public void clear() throws IOException { + if (employeeRepository != null) { + if (!employeeRepository.isDropped() + && employeeRepository.isOpen()) { + employeeRepository.remove(ALL); + employeeRepository.unsubscribe(listener); + employeeRepository.close(); + } + } + + if (db != null) { + db.commit(); + db.close(); + } + + if (!inMemory) { + deleteDb(fileName); + } + } + + private Callable listenerPrepared(final EventType action) { + return () -> listener.getAction() == action; + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/event/SampleListenerCollection.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/event/SampleListenerCollection.java new file mode 100644 index 000000000..6297ecbc1 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/event/SampleListenerCollection.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.event; + +import lombok.Getter; +import org.dizitart.no2.collection.events.CollectionEventInfo; +import org.dizitart.no2.collection.events.CollectionEventListener; +import org.dizitart.no2.collection.events.EventType; + +/** + * @author Anindya Chatterjee. + */ +@Getter +class SampleListenerCollection implements CollectionEventListener { + private EventType action; + private Object item; + + @Override + public void onEvent(CollectionEventInfo eventInfo) { + if (eventInfo != null) { + this.action = eventInfo.getEventType(); + this.item = eventInfo.getItem(); + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/migrate/MigrationTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/migrate/MigrationTest.java new file mode 100644 index 000000000..9b4eeab29 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/migrate/MigrationTest.java @@ -0,0 +1,584 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.migrate; + +import com.github.javafaker.Faker; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.Constants; +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.exceptions.MigrationException; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.migration.Instructions; +import org.dizitart.no2.migration.Migration; +import org.dizitart.no2.migration.TypeConverter; +import org.dizitart.no2.mvstore.MVStoreModule; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.util.UUID; + +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.integration.TestUtil.*; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class MigrationTest { + private final String dbPath = getRandomTempDbFile(); + private Nitrite db; + private Faker faker; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + db = createDb(dbPath); + faker = new Faker(); + } + + @After + public void cleanUp() { + if (!db.isClosed()) { + db.close(); + } + + deleteDb(dbPath); + } + + @Test + public void testRepositoryMigrate() { + ObjectRepository oldRepo = db.getRepository(OldClass.class, "demo1"); + for (int i = 0; i < 10; i++) { + OldClass old = new OldClass(); + old.setEmpId(String.valueOf(faker.number().randomNumber())); + old.setFirstName(faker.name().firstName()); + old.setLastName(faker.name().lastName()); + old.setUuid(UUID.randomUUID().toString()); + + OldClass.Literature literature = new OldClass.Literature(); + literature.setRatings((float) faker.number().randomDouble(2, 1, 5)); + literature.setText(faker.lorem().paragraph()); + old.setLiterature(literature); + + oldRepo.insert(old); + } + + db.close(); + + Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { + @Override + public void migrate(Instructions instruction) { + instruction.forDatabase() + .addPassword("test-user", "test-password"); + + instruction.forRepository(OldClass.class, "demo1") + .renameRepository("new", null) + .changeDataType("empId", (TypeConverter) Long::parseLong) + .changeIdField(Fields.withNames("uuid"), Fields.withNames("empId")) + .deleteField("uuid") + .renameField("lastName", "familyName") + .addField("fullName", document -> document.get("firstName", String.class) + " " + + document.get("familyName", String.class)) + .dropIndex("firstName") + .dropIndex("literature.text") + .changeDataType("literature.ratings", (TypeConverter) Math::round); + } + }; + + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compress(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate("test-user", "test-password"); + + ObjectRepository newRepo = db.getRepository(NewClass.class); + assertEquals(newRepo.size(), 10); + assertTrue(db.listCollectionNames().isEmpty()); + assertTrue(db.listKeyedRepository().isEmpty()); + + assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 2); + } + + @Test + public void testCollectionMigrate() { + NitriteCollection collection = db.getCollection("test"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + document.put("bloodGroup", faker.name().bloodGroup()); + document.put("age", faker.number().randomDigit()); + + collection.insert(document); + } + + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "firstName"); + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "bloodGroup"); + db.close(); + + Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { + @Override + public void migrate(Instructions instruction) { + instruction.forDatabase() + .addPassword("test-user", "test-password"); + + instruction.forCollection("test") + .rename("testCollectionMigrate") + .deleteField("lastName"); + } + }; + + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate("test-user", "test-password"); + + collection = db.getCollection("testCollectionMigrate"); + assertTrue(collection.hasIndex("firstName")); + assertEquals(collection.size(), 10); + assertEquals(db.listCollectionNames().size(), 1); + assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 2); + db.close(); + + migration = new Migration(2, 3) { + @Override + public void migrate(Instructions instructions) { + instructions.forDatabase() + .changePassword("test-user", "test-password", "password"); + + instructions.forCollection("testCollectionMigrate") + .dropIndex("firstName") + .deleteField("bloodGroup") + .addField("name", document -> faker.name().fullName()) + .addField("address") + .addField("vehicles", 1) + .renameField("age", "ageGroup") + .createIndex(IndexType.NON_UNIQUE, "ageGroup"); + } + }; + + storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(3) + .addMigrations(migration) + .openOrCreate("test-user", "password"); + + collection = db.getCollection("testCollectionMigrate"); + assertEquals(collection.size(), 10); + assertEquals(db.listCollectionNames().size(), 1); + assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 3); + + assertFalse(collection.hasIndex("firstName")); + assertTrue(collection.hasIndex("ageGroup")); + assertEquals(collection.find(where("age").notEq(null)).size(), 0); + } + + @Test(expected = MigrationException.class) + public void testOpenWithoutSchemaVersion() { + NitriteCollection collection = db.getCollection("test"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + + collection.insert(document); + } + db.close(); + + Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { + @Override + public void migrate(Instructions instruction) { + + instruction.forCollection("test") + .rename("testOpenWithoutSchemaVersion") + .deleteField("lastName"); + } + }; + + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testOpenWithoutSchemaVersion"); + assertEquals(collection.size(), 10); + db.close(); + + storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .openOrCreate(); + + collection = db.getCollection("testOpenWithoutSchemaVersion"); + assertEquals(collection.size(), 10); + } + + @Test + public void testDescendingSchema() { + NitriteCollection collection = db.getCollection("test"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + + collection.insert(document); + } + db.close(); + + Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { + @Override + public void migrate(Instructions instruction) { + + instruction.forCollection("test") + .rename("testDescendingSchema") + .deleteField("lastName"); + } + }; + + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testDescendingSchema"); + assertEquals(collection.size(), 10); + db.close(); + + migration = new Migration(2, Constants.INITIAL_SCHEMA_VERSION) { + @Override + public void migrate(Instructions instructions) { + + instructions.forCollection("testDescendingSchema") + .rename("test"); + } + }; + + storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(1) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + db.close(); + } + + @Test + public void testMigrationWithoutVersion() { + NitriteCollection collection = db.getCollection("test"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + + collection.insert(document); + } + db.close(); + + Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { + @Override + public void migrate(Instructions instruction) { + + instruction.forCollection("test") + .rename("testMigrationWithoutVersion") + .deleteField("lastName"); + } + }; + + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testMigrationWithoutVersion"); + assertEquals(collection.size(), 0); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + db.close(); + } + + @Test + public void testWrongSchemaVersionNoMigration() { + NitriteCollection collection = db.getCollection("testWrongSchemaVersionNoMigration"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + + collection.insert(document); + } + db.close(); + + Migration migration = new Migration(1, 2) { + @Override + public void migrate(Instructions instruction) { + + instruction.forCollection("testWrongSchemaVersionNoMigration") + .rename("test") + .deleteField("lastName"); + } + }; + + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testWrongSchemaVersionNoMigration"); + assertEquals(collection.size(), 0); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + db.close(); + + migration = new Migration(2, 3) { + @Override + public void migrate(Instructions instructions) { + instructions.forCollection("test") + .rename("testWrongSchemaVersionNoMigration"); + } + }; + + storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testWrongSchemaVersionNoMigration"); + assertEquals(collection.size(), 0); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + db.close(); + } + + @Test + public void testReOpenAfterMigration() { + NitriteCollection collection = db.getCollection("testReOpenAfterMigration"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + + collection.insert(document); + } + db.close(); + + Migration migration = new Migration(1, 2) { + @Override + public void migrate(Instructions instruction) { + + instruction.forCollection("testReOpenAfterMigration") + .rename("test") + .deleteField("lastName"); + } + }; + + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testReOpenAfterMigration"); + assertEquals(collection.size(), 0); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + db.close(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testReOpenAfterMigration"); + assertEquals(collection.size(), 0); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + db.close(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .openOrCreate(); + + collection = db.getCollection("testReOpenAfterMigration"); + assertEquals(collection.size(), 0); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + } + + @Test + public void testMultipleMigrations() { + NitriteCollection collection = db.getCollection("testMultipleMigrations"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + + collection.insert(document); + } + db.close(); + + Migration migration1 = new Migration(1, 2) { + @Override + public void migrate(Instructions instruction) { + + instruction.forCollection("testMultipleMigrations") + .rename("test"); + } + }; + + Migration migration2 = new Migration(2, 3) { + @Override + public void migrate(Instructions instruction) { + instruction.forCollection("test") + .addField("fullName", "Dummy Name"); + } + }; + + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration1, migration2) + .openOrCreate(); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + assertEquals(collection.find(where("fullName").eq("Dummy Name")).size(), 0); + db.close(); + + Migration migration3 = new Migration(3, 4) { + @Override + public void migrate(Instructions instruction) { + instruction.forCollection("test") + .addField("age", 10); + } + }; + + storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .compressHigh(true) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(4) + .addMigrations(migration1, migration2, migration3) + .openOrCreate(); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + assertEquals(collection.find(where("fullName").eq("Dummy Name")).size(), 10); + assertEquals(collection.find(where("age").eq(10)).size(), 10); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/migrate/NewClass.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/migrate/NewClass.java new file mode 100644 index 000000000..56ef25c22 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/migrate/NewClass.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.migrate; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Entity; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +/** + * @author Anindya Chatterjee + */ +@Data +@Entity(value = "new", indices = { + @Index(value = "familyName", type = IndexType.NON_UNIQUE), + @Index(value = "fullName", type = IndexType.NON_UNIQUE), + @Index(value = "literature.ratings", type = IndexType.NON_UNIQUE), +}) +public class NewClass implements Mappable { + @Id + private Long empId; + private String firstName; + private String familyName; + private String fullName; + private Literature literature; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("empId", empId) + .put("firstName", firstName) + .put("familyName", familyName) + .put("fullName", fullName) + .put("literature", literature.write(mapper)); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + empId = document.get("empId", Long.class); + firstName = document.get("firstName", String.class); + familyName = document.get("familyName", String.class); + fullName = document.get("fullName", String.class); + + Document doc = document.get("literature", Document.class); + literature = new Literature(); + literature.read(mapper, doc); + } + + @Data + public static class Literature implements Mappable { + private String text; + private Integer ratings; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("text", text) + .put("ratings", ratings); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + text = document.get("text", String.class); + ratings = document.get("ratings", Integer.class); + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/migrate/OldClass.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/migrate/OldClass.java new file mode 100644 index 000000000..3bbb09b4e --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/migrate/OldClass.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.migrate; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Entity; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +/** + * @author Anindya Chatterjee + */ +@Data +@Entity(value = "old", indices = { + @Index(value = "firstName", type = IndexType.NON_UNIQUE), + @Index(value = "lastName", type = IndexType.NON_UNIQUE), + @Index(value = "literature.text", type = IndexType.FULL_TEXT), + @Index(value = "literature.ratings", type = IndexType.NON_UNIQUE), +}) +public class OldClass implements Mappable { + @Id + private String uuid; + private String empId; + private String firstName; + private String lastName; + private Literature literature; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("empId", empId) + .put("uuid", uuid) + .put("firstName", firstName) + .put("lastName", lastName) + .put("literature", literature.write(mapper)); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + empId = document.get("empId", String.class); + uuid = document.get("uuid", String.class); + firstName = document.get("firstName", String.class); + lastName = document.get("lastName", String.class); + + Document doc = document.get("literature", Document.class); + literature = new Literature(); + literature.read(mapper, doc); + } + + @Data + public static class Literature implements Mappable { + private String text; + private Float ratings; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("text", text) + .put("ratings", ratings); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + text = document.get("text", String.class); + ratings = document.get("ratings", Float.class); + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/mvstore/NitriteMapStressTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/mvstore/NitriteMapStressTest.java new file mode 100644 index 000000000..82986a8c7 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/mvstore/NitriteMapStressTest.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.mvstore; + +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.store.NitriteStore; +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; + +import java.util.UUID; + +import static org.dizitart.no2.integration.TestUtil.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * @author Anindya Chatterjee. + */ +public class NitriteMapStressTest { + private final String dbPath = getRandomTempDbFile(); + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Test + public void testWithInsertReadUpdate() { + db = createDb(dbPath); + + NitriteStore nitriteStore = db.getStore(); + NitriteMap nitriteMap = nitriteStore.openMap("testWithInsertReadUpdate", + String.class, Document.class); + + int count = 10000; + for (int i = 0; i < count; i++) { + Document record = Document.createDocument(); + record.put("firstName", UUID.randomUUID().toString()); + record.put("failed", false); + record.put("lastName", UUID.randomUUID().toString()); + record.put("processed", false); + + nitriteMap.put(UUID.randomUUID().toString(), record); + } + + for (Pair entry : nitriteMap.entries()) { + String key = entry.getFirst(); + Document record = entry.getSecond(); + + record.put("processed", true); + + nitriteMap.put(key, record); + } + + db.close(); + } + + @Test + public void testNullKey() { + db = createDb(dbPath); + NitriteStore nitriteStore = db.getStore(); + NitriteMap nitriteMap = nitriteStore.openMap("testNullKey", + String.class, Document.class); + nitriteMap.put(null, Document.createDocument()); + + assertNotNull(nitriteMap.get(null)); + assertEquals(nitriteMap.size(), 1); + + nitriteMap.put(null, Document.createDocument("first", 1)); + assertNotNull(nitriteMap.get(null)); + assertEquals(nitriteMap.size(), 1); + } + + @Test(expected = ValidationException.class) + public void testNullValue() { + db = createDb(dbPath); + NitriteStore nitriteStore = db.getStore(); + NitriteMap nitriteMap = nitriteStore.openMap("testNullValue", + String.class, Document.class); + nitriteMap.put(null, null); + } + + @Test(expected = ValidationException.class) + public void testNullPutIfAbsent() { + db = createDb(dbPath); + NitriteStore nitriteStore = db.getStore(); + NitriteMap nitriteMap = nitriteStore.openMap("testNullPutIfAbsent", + String.class, Document.class); + nitriteMap.putIfAbsent(null, null); + } + + @After + public void tearDown() { + if (db != null && !db.isClosed()) { + db.close(); + } + deleteDb(dbPath); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/mvstore/NitriteStoreEventTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/mvstore/NitriteStoreEventTest.java new file mode 100644 index 000000000..f9d66266c --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/mvstore/NitriteStoreEventTest.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.mvstore; + +import lombok.Data; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.mvstore.MVStoreModule; +import org.dizitart.no2.store.events.EventInfo; +import org.dizitart.no2.store.events.StoreEventListener; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +import static org.awaitility.Awaitility.await; +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee + */ +public class NitriteStoreEventTest { + private String dbFile; + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void before() { + dbFile = getRandomTempDbFile(); + } + + @After + public void cleanup() throws IOException { + if (db != null && !db.isClosed()) { + db.close(); + } + + deleteDb(dbFile); + } + + @Test + public void testStoreEvents() { + TestStoreEventListener listener = new TestStoreEventListener(); + assertFalse(listener.opened); + assertFalse(listener.committed); + assertFalse(listener.closing); + assertFalse(listener.closed); + + MVStoreModule module = MVStoreModule.withConfig() + .filePath(dbFile) + .addStoreEventListener(listener) + .build(); + + db = Nitrite.builder() + .loadModule(module) + .fieldSeparator(".") + .openOrCreate(); + + await().atMost(1, TimeUnit.SECONDS).until(() -> listener.opened); + assertTrue(listener.opened); + assertFalse(listener.committed); + assertFalse(listener.closing); + assertFalse(listener.closed); + + db.commit(); + + await().atMost(1, TimeUnit.SECONDS).until(() -> listener.committed); + assertTrue(listener.opened); + assertTrue(listener.committed); + assertFalse(listener.closing); + assertFalse(listener.closed); + + db.close(); + + await().atMost(1, TimeUnit.SECONDS).until(() -> listener.closed); + assertTrue(listener.opened); + assertTrue(listener.committed); + assertTrue(listener.closing); + assertTrue(listener.closed); + + db.getStore().unsubscribe(listener); + } + + @Data + private static class TestStoreEventListener implements StoreEventListener { + private boolean opened; + private boolean committed; + private boolean closing; + private boolean closed; + + @Override + public void onEvent(EventInfo eventInfo) { + switch (eventInfo.getEvent()) { + case Opened: + opened = true; + break; + case Commit: + committed = true; + break; + case Closing: + closing = true; + break; + case Closed: + closed = true; + break; + } + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/BaseObjectRepositoryTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/BaseObjectRepositoryTest.java new file mode 100644 index 000000000..2d33d0c43 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/BaseObjectRepositoryTest.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.integration.repository.data.*; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteBuilder; +import org.dizitart.no2.mvstore.MVStoreModule; +import org.dizitart.no2.mvstore.MVStoreModuleBuilder; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.Arrays; +import java.util.Collection; + +import static org.dizitart.no2.filters.Filter.ALL; +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; + +@RunWith(value = Parameterized.class) +public abstract class BaseObjectRepositoryTest { + @Parameterized.Parameter + public boolean inMemory = false; + @Parameterized.Parameter(value = 1) + public boolean isProtected = false; + @Parameterized.Parameter(value = 2) + public boolean isCompressed = false; + @Parameterized.Parameter(value = 3) + public boolean isAutoCommit = false; + + protected Nitrite db; + protected ObjectRepository companyRepository; + protected ObjectRepository employeeRepository; + protected ObjectRepository aObjectRepository; + protected ObjectRepository cObjectRepository; + protected ObjectRepository bookRepository; + + private final String fileName = getRandomTempDbFile(); + + @Rule + public Retry retry = new Retry(3); + + @Parameterized.Parameters(name = "InMemory = {0}, Protected = {1}, " + + "Compressed = {2}, AutoCommit = {3}") + public static Collection data() { + return Arrays.asList(new Object[][]{ + {false, false, false, false}, + {false, false, false, true}, + {false, false, true, false}, + {false, false, true, true}, + {false, true, false, false}, + {false, true, false, true}, + {false, true, true, false}, + {false, true, true, true}, + {true, false, false, false}, + {true, false, false, true}, + {true, false, true, false}, + {true, false, true, true}, + {true, true, false, false}, + {true, true, false, true}, + {true, true, true, false}, + {true, true, true, true}, + }); + } + + @Before + public void setUp() { + openDb(); + + companyRepository = db.getRepository(Company.class); + employeeRepository = db.getRepository(Employee.class); + + aObjectRepository = db.getRepository(ClassA.class); + cObjectRepository = db.getRepository(ClassC.class); + + bookRepository = db.getRepository(Book.class); + + for (int i = 0; i < 10; i++) { + Company company = DataGenerator.generateCompanyRecord(); + companyRepository.insert(company); + Employee employee = DataGenerator.generateEmployee(); + employee.setEmpId((long) i + 1); + employeeRepository.insert(employee); + + aObjectRepository.insert(ClassA.create(i + 50)); + cObjectRepository.insert(ClassC.create(i + 30)); + + Book book = DataGenerator.randomBook(); + bookRepository.insert(book); + } + } + + protected void openDb() { + MVStoreModuleBuilder builder = MVStoreModule.withConfig(); + + if (isCompressed) { + builder.compress(true); + } + + if (!isAutoCommit) { + builder.autoCommit(false); + } + + if (!inMemory) { + builder.filePath(fileName); + } + + MVStoreModule storeModule = builder.build(); + NitriteBuilder nitriteBuilder = Nitrite.builder() + .fieldSeparator(".") + .loadModule(storeModule); + + if (isProtected) { + db = nitriteBuilder.openOrCreate("test-user", "test-password"); + } else { + db = nitriteBuilder.openOrCreate(); + } + } + + @After + public void clear() throws Exception { + if (companyRepository != null && !companyRepository.isDropped()) { + companyRepository.remove(ALL); + } + + if (employeeRepository != null && !employeeRepository.isDropped()) { + employeeRepository.remove(ALL); + } + + if (aObjectRepository != null && !aObjectRepository.isDropped()) { + aObjectRepository.remove(ALL); + } + + if (cObjectRepository != null && !cObjectRepository.isDropped()) { + cObjectRepository.remove(ALL); + } + + if (bookRepository != null && !bookRepository.isDropped()) { + bookRepository.remove(ALL); + } + + if (db != null && !db.isClosed()) { + db.commit(); + db.close(); + } + + if (!inMemory) { + deleteDb(fileName); + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/CustomFieldSeparatorTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/CustomFieldSeparatorTest.java new file mode 100644 index 000000000..965a8d8ab --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/CustomFieldSeparatorTest.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.integration.repository.data.Company; +import org.dizitart.no2.integration.repository.data.Note; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.mvstore.MVStoreModule; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; +import org.dizitart.no2.repository.annotations.Indices; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.Serializable; +import java.util.Date; + +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee + */ +public class CustomFieldSeparatorTest { + private final String fileName = getRandomTempDbFile(); + private ObjectRepository repository; + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + MVStoreModule module = MVStoreModule.withConfig() + .filePath(fileName) + .compress(true) + .build(); + + db = Nitrite.builder() + .loadModule(module) + .fieldSeparator(":") + .openOrCreate(); + + repository = db.getRepository(EmployeeForCustomSeparator.class); + } + + @After + public void reset() { + (new NitriteConfig()).fieldSeparator("."); + if (db != null && !db.isClosed()) { + db.close(); + deleteDb(fileName); + } + } + + @Test + public void testFieldSeparator() { + assertEquals(NitriteConfig.getFieldSeparator(), ":"); + } + + @Test + public void testFindByEmbeddedField() { + EmployeeForCustomSeparator employee = new EmployeeForCustomSeparator(); + employee.setCompany(new Company()); + employee.setEmployeeNote(new Note()); + + employee.setEmpId(123L); + employee.setJoinDate(new Date()); + employee.setBlob(new byte[0]); + employee.setAddress("Dummy address"); + + employee.getCompany().setCompanyId(987L); + employee.getCompany().setCompanyName("Dummy Company"); + employee.getCompany().setDateCreated(new Date()); + + employee.getEmployeeNote().setNoteId(567L); + employee.getEmployeeNote().setText("Dummy Note"); + + repository.insert(employee); + + assertEquals(repository.find(where("employeeNote.text").eq("Dummy Note")).size(), 0); + assertEquals(repository.find(where("employeeNote:text").text("Dummy Note")).size(), 1); + + assertEquals(repository.find(where("company.companyName").eq("Dummy Company")).size(), 0); + assertEquals(repository.find(where("company:companyName").eq("Dummy Company")).size(), 1); + } + + @ToString + @EqualsAndHashCode + @Indices({ + @Index(value = "joinDate", type = IndexType.NON_UNIQUE), + @Index(value = "address", type = IndexType.FULL_TEXT), + @Index(value = "employeeNote:text", type = IndexType.FULL_TEXT) + }) + public static class EmployeeForCustomSeparator implements Serializable, Mappable { + @Id + @Getter + @Setter + private Long empId; + + @Getter + @Setter + private Date joinDate; + + @Getter + @Setter + private String address; + + @Getter + @Setter + private Company company; + + @Getter + @Setter + private byte[] blob; + + @Getter + @Setter + private Note employeeNote; + + EmployeeForCustomSeparator() { + } + + public EmployeeForCustomSeparator(EmployeeForCustomSeparator copy) { + empId = copy.empId; + joinDate = copy.joinDate; + address = copy.address; + company = copy.company; + blob = copy.blob; + employeeNote = copy.employeeNote; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument().put("empId", empId) + .put("joinDate", joinDate) + .put("address", address) + .put("blob", blob) + .put("company", company.write(mapper)) + .put("employeeNote", employeeNote.write(mapper)); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + empId = document.get("empId", Long.class); + joinDate = document.get("joinDate", Date.class); + address = document.get("address", String.class); + blob = document.get("blob", byte[].class); + employeeNote = new Note(); + Document doc = document.get("employeeNote", Document.class); + employeeNote.read(mapper, doc); + company = new Company(); + doc = document.get("company", Document.class); + company.read(mapper, doc); + } + } + +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/FieldProcessorTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/FieldProcessorTest.java new file mode 100644 index 000000000..73a093082 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/FieldProcessorTest.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.integration.repository.data.EncryptedPerson; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.common.crypto.AESEncryptor; +import org.dizitart.no2.common.crypto.Encryptor; +import org.dizitart.no2.common.processors.Processor; +import org.dizitart.no2.common.processors.StringFieldEncryptionProcessor; +import org.dizitart.no2.exceptions.NitriteSecurityException; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.store.NitriteMap; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.nio.charset.StandardCharsets; +import java.util.Date; +import java.util.List; + +import static org.dizitart.no2.common.util.Iterables.toList; +import static org.dizitart.no2.common.util.ObjectUtils.findRepositoryName; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class FieldProcessorTest extends BaseObjectRepositoryTest { + private ObjectRepository persons; + private StringFieldEncryptionProcessor fieldProcessor; + + @Before + public void setUp() { + super.setUp(); + persons = db.getRepository(EncryptedPerson.class); + fieldProcessor = new StringFieldEncryptionProcessor("s3k4e8"); + fieldProcessor.addFields("creditCardNumber", "cvv"); + + EncryptedPerson person = new EncryptedPerson(); + person.setName("John Doe"); + person.setCreditCardNumber("5548960345687452"); + person.setCvv("007"); + person.setExpiryDate(new Date()); + + persons.insert(person); + + persons.addProcessor(fieldProcessor); + + person = new EncryptedPerson(); + person.setName("Jane Doe"); + person.setCreditCardNumber("5500960345687452"); + person.setCvv("008"); + person.setExpiryDate(new Date()); + persons.insert(person); + } + + @Test + public void testFieldEncryptionInNitriteMap() { + NitriteMap nitriteMap = persons.getDocumentCollection().getStore() + .openMap(findRepositoryName(EncryptedPerson.class, null), NitriteId.class, Document.class); + + List documents = toList(nitriteMap.values()); + for (Document document : documents) { + if (document.get("creditCardNumber", String.class).equalsIgnoreCase("5548960345687452")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("creditCardNumber", String.class).equalsIgnoreCase("5500960345687452")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("cvv", String.class).equalsIgnoreCase("008")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("cvv", String.class).equalsIgnoreCase("007")) { + Assert.fail("unencrypted secret text found"); + } + } + } + + @Test + public void testSuccessfulDecryption() { + EncryptedPerson person = persons.find(where("name").eq("Jane Doe")).firstOrNull(); + assertNotNull(person); + + assertEquals(person.getCreditCardNumber(), "5500960345687452"); + assertEquals(person.getCvv(), "008"); + + person = persons.find(where("name").eq("John Doe")).firstOrNull(); + assertNotNull(person); + + assertEquals(person.getCreditCardNumber(), "5548960345687452"); + assertEquals(person.getCvv(), "007"); + } + + @Test(expected = NitriteSecurityException.class) + public void testFailedDecryption() { + ObjectRepository testPersons = db.getRepository(EncryptedPerson.class, "test"); + + Encryptor encryptor = new AESEncryptor("secret"); + Encryptor wrongEncryptor = new AESEncryptor("secret", "AES/GCM/NoPadding", + 5, 5, 5); + + testPersons.addProcessor(new Processor() { + @Override + public Document processBeforeWrite(Document document) { + String creditCardNumber = document.get("creditCardNumber", String.class); + String encryptedCreditCardNumber = encryptor.encrypt(creditCardNumber.getBytes(StandardCharsets.UTF_8)); + document.put("creditCardNumber", encryptedCreditCardNumber); + return document; + } + + @Override + public Document processAfterRead(Document document) { + String encryptedCreditCardNumber = document.get("creditCardNumber", String.class); + String creditCardNumber = wrongEncryptor.decrypt(encryptedCreditCardNumber); + document.put("creditCardNumber", creditCardNumber); + return document; + } + }); + + EncryptedPerson person = new EncryptedPerson(); + person.setName("John Doe"); + person.setCreditCardNumber("5548960345687452"); + person.setCvv("007"); + person.setExpiryDate(new Date()); + + testPersons.insert(person); + + person = new EncryptedPerson(); + person.setName("Jane Doe"); + person.setCreditCardNumber("5500960345687452"); + person.setCvv("008"); + person.setExpiryDate(new Date()); + testPersons.insert(person); + + testPersons.find(where("name").eq("Jane Doe")).firstOrNull(); + } + + @Test + public void testSearchOnEncryptedField() { + EncryptedPerson person = persons.find(where("cvv").eq("008")).firstOrNull(); + assertNull(person); + } + + @Test + public void testUpdateEncryptedField() { + EncryptedPerson person = new EncryptedPerson(); + person.setName("John Doe"); + person.setCreditCardNumber("00000000000000"); + person.setCvv("007"); + person.setExpiryDate(new Date()); + + WriteResult writeResult = persons.update(where("name").eq("John Doe"), person); + assertEquals(writeResult.getAffectedCount(), 1); + + person = persons.find(where("name").eq("John Doe")).firstOrNull(); + assertNotNull(person); + + assertEquals(person.getCreditCardNumber(), "00000000000000"); + assertEquals(person.getCvv(), "007"); + } + + @Test + public void testIndexOnEncryptedField() { + persons.createIndex("cvv"); + EncryptedPerson person = persons.find(where("cvv").eq("008")).firstOrNull(); + assertNull(person); + } + + @Test + public void testRemoveProcessor() { + EncryptedPerson person = persons.find(where("cvv").eq("008")).firstOrNull(); + assertNull(person); + + person = persons.find(where("creditCardNumber").eq("5548960345687452")).firstOrNull(); + assertNull(person); + + persons.removeProcessor(fieldProcessor); + + person = persons.find(where("cvv").eq("008")).firstOrNull(); + assertNotNull(person); + + person = persons.find(where("creditCardNumber").eq("5548960345687452")).firstOrNull(); + assertNotNull(person); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/InternalClass.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/InternalClass.java new file mode 100644 index 000000000..1a52708ce --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/InternalClass.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Data +class InternalClass implements Mappable { + @Id + private long id; + private String name; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("id", id) + .put("name", name); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Long.class); + name = document.get("name", String.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/NitriteIdAsIdTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/NitriteIdAsIdTest.java new file mode 100644 index 000000000..dedd5e256 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/NitriteIdAsIdTest.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.integration.repository.data.WithNitriteId; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.common.util.Iterables; +import org.dizitart.no2.exceptions.InvalidIdException; +import org.dizitart.no2.integration.TestUtil; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.IOException; + +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * @author Anindya Chatterjee + */ +public class NitriteIdAsIdTest { + private final String fileName = getRandomTempDbFile(); + private Nitrite db; + private ObjectRepository repo; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void before() { + db = TestUtil.createDb(fileName); + repo = db.getRepository(WithNitriteId.class); + } + + @After + public void after() throws IOException { + db.close(); + deleteDb(fileName); + } + + @Test + public void testNitriteIdField() { + WithNitriteId item1 = new WithNitriteId(); + item1.name = "first"; + + WithNitriteId item2 = new WithNitriteId(); + item2.name = "second"; + + repo.insert(item1, item2); + + Cursor cursor = repo.find(); + for (WithNitriteId withNitriteId : cursor) { + System.out.println(withNitriteId.name); + assertNotNull(withNitriteId.idField); + } + + WithNitriteId withNitriteId = cursor.firstOrNull(); + withNitriteId.name = "third"; + + NitriteId id = withNitriteId.idField; + repo.update(withNitriteId); + + WithNitriteId byId = repo.getById(id); + assertEquals(withNitriteId, byId); + assertEquals(repo.size(), 2); + } + + @Test(expected = InvalidIdException.class) + public void setIdDuringInsert() { + WithNitriteId item1 = new WithNitriteId(); + item1.name = "first"; + item1.idField = NitriteId.newId(); + + repo.insert(item1); + } + + @Test + public void changeIdDuringUpdate() { + WithNitriteId item2 = new WithNitriteId(); + item2.name = "second"; + WriteResult result = repo.insert(item2); + NitriteId nitriteId = Iterables.firstOrNull(result); + WithNitriteId byId = repo.getById(nitriteId); + byId.idField = NitriteId.newId(); + + result = repo.update(byId); + assertEquals(result.getAffectedCount(), 0); + assertEquals(repo.size(), 1); + } + +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/ObjectCursorTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/ObjectCursorTest.java new file mode 100644 index 000000000..5be20ded7 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/ObjectCursorTest.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.integration.repository.data.Employee; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.repository.Cursor; +import org.junit.Test; + +import java.util.AbstractCollection; + +/** + * @author Anindya Chatterjee + */ +public class ObjectCursorTest extends BaseObjectRepositoryTest { + + @Test(expected = ValidationException.class) + public void testProjectForInterface() { + Cursor cursor = employeeRepository.find(); + cursor.project(Comparable.class); + } + + @Test(expected = ValidationException.class) + public void testProjectForPrimitive() { + Cursor cursor = employeeRepository.find(); + cursor.project(int.class); + } + + @Test(expected = ValidationException.class) + public void testProjectForArray() { + Cursor cursor = employeeRepository.find(); + cursor.project(String[].class); + } + + @Test(expected = ValidationException.class) + public void testProjectForAbstractClass() { + Cursor cursor = employeeRepository.find(); + cursor.project(AbstractCollection.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryNegativeTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryNegativeTest.java new file mode 100644 index 000000000..e070d485d --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryNegativeTest.java @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.integration.repository.data.*; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.exceptions.*; +import org.dizitart.no2.integration.TestUtil; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.IOException; + +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class ObjectRepositoryNegativeTest { + private final String dbPath = getRandomTempDbFile(); + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + db = TestUtil.createDb(dbPath); + } + + @After + public void close() throws IOException { + db.close(); + db = null; + deleteDb(dbPath); + } + + @Test(expected = ObjectMappingException.class) + public void testWithCircularReference() { + ObjectRepository repository = db.getRepository(WithCircularReference.class); + + WithCircularReference parent = new WithCircularReference(); + parent.setName("parent"); + WithCircularReference object = new WithCircularReference(); + object.setName("test"); + object.setParent(parent); + // circular reference + parent.setParent(object); + + WriteResult result = repository.insert(object); + for (NitriteId id : result) { + WithCircularReference instance = repository.getById(id); + assertEquals(instance.getName(), object.getName()); + assertEquals(instance.getParent().getName(), object.getParent().getName()); + } + } + + @Test(expected = ObjectMappingException.class) + public void testWithCustomConstructor() { + ObjectRepository repository = db.getRepository(WithCustomConstructor.class); + + WithCustomConstructor object = new WithCustomConstructor("test", 2L); + + WriteResult result = repository.insert(object); + for (NitriteId id : result) { + WithCustomConstructor instance = repository.getById(id); + assertEquals(object.getName(), instance.getName()); + assertEquals(object.getNumber(), instance.getNumber()); + } + } + + @Test(expected = InvalidIdException.class) + public void testWithEmptyStringId() { + ObjectRepository repository = db.getRepository(WithEmptyStringId.class); + WithEmptyStringId object = new WithEmptyStringId(); + object.setName(""); // empty id value + + WriteResult result = repository.insert(object); + for (NitriteId id : result) { + WithEmptyStringId instance = repository.getById(id); + assertEquals(instance, object); + } + } + + @Test(expected = InvalidIdException.class) + public void testWithNullId() { + ObjectRepository repository = db.getRepository(WithNullId.class); + WithNullId object = new WithNullId(); + + WriteResult result = repository.insert(object); + for (NitriteId id : result) { + WithNullId instance = repository.getById(id); + assertEquals(instance, object); + } + } + + @Test(expected = ValidationException.class) + public void testWithValueTypeRepository() { + ObjectRepository repository = db.getRepository(String.class); + repository.insert("test"); + } + + @Test(expected = InvalidOperationException.class) + public void testFindResultRemove() { + ObjectRepository repository = db.getRepository(Employee.class); + repository.insert(DataGenerator.generateEmployee()); + RecordStream result = repository.find(); + result.iterator().remove(); + } + + @Test(expected = IndexingException.class) + public void testWithObjectId() { + ObjectRepository repository = db.getRepository(WithObjectId.class); + WithOutId id = new WithOutId(); + id.setName("test"); + id.setNumber(1); + + WithObjectId object = new WithObjectId(); + object.setWithOutId(id); + repository.insert(object); + } + + @Test(expected = NotIdentifiableException.class) + public void testUpdateNoId() { + ObjectRepository repository = db.getRepository(WithOutId.class); + WithOutId object = new WithOutId(); + object.setName("name"); + object.setNumber(1L); + repository.update(object); + } + + @Test(expected = NotIdentifiableException.class) + public void testRemoveNoId() { + ObjectRepository repository = db.getRepository(WithOutId.class); + WithOutId object = new WithOutId(); + object.setName("name"); + object.setNumber(1L); + repository.remove(object); + } + + @Test(expected = ValidationException.class) + public void testProjectionFailedInstantiate() { + ObjectRepository repository = db.getRepository(WithOutId.class); + WithOutId object = new WithOutId(); + object.setName("name"); + object.setNumber(1L); + repository.insert(object); + + RecordStream project = repository.find().project(NitriteId.class); + assertNull(project.toList()); + } + + @Test(expected = ValidationException.class) + public void testNullInsert() { + ObjectRepository repository = db.getRepository(WithOutId.class); + repository.insert(null); + } + + @Test(expected = InvalidIdException.class) + public void testGetByNullId() { + ObjectRepository repository = db.getRepository(WithPublicField.class); + WithPublicField object = new WithPublicField(); + object.name = "test"; + object.number = 2; + + repository.insert(object); + WithPublicField instance = repository.getById(null); + assertEquals(object.name, instance.name); + assertEquals(object.number, instance.number); + } + + @Test + public void testExternalNitriteId() { + ObjectRepository repository = db.getRepository(WithNitriteId.class); + WithNitriteId obj = new WithNitriteId(); + NitriteId id = NitriteId.createId("1"); + obj.setIdField(id); + obj.setName("testExternalNitriteId"); + WriteResult result = repository.update(obj, true); + + obj = new WithNitriteId(); + id = result.iterator().next(); + obj.setIdField(id); + obj.setName("testExternalNitriteId"); + result = repository.update(obj, true); + assertNotEquals(id.getIdValue(), result.iterator().next().getIdValue()); + } + + @Test(expected = IndexingException.class) + public void testWithoutEmbeddedId() { + ObjectRepository repository = db.getRepository(WithoutEmbeddedId.class); + assertNull(repository); + } + + @Test(expected = InvalidIdException.class) + public void testGetByWrongIdType() { + ObjectRepository repository = db.getRepository(WithPublicField.class); + WithPublicField object = new WithPublicField(); + object.name = "test"; + object.number = 2; + + repository.insert(object); + + NitriteId id = NitriteId.createId("1"); + WithPublicField instance = repository.getById(id); + assertEquals(object.name, instance.name); + assertEquals(object.number, instance.number); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryTest.java new file mode 100644 index 000000000..16455e07d --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryTest.java @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import com.github.javafaker.Faker; +import lombok.Data; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.integration.repository.data.*; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.meta.Attributes; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.MappableMapper; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.mvstore.MVStoreModule; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Entity; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.IOException; +import java.util.Date; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.awaitility.Awaitility.await; +import static org.dizitart.no2.common.module.NitriteModule.module; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class ObjectRepositoryTest { + private final String dbPath = getRandomTempDbFile(); + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + NitriteMapper mapper = new MappableMapper(); + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath(dbPath) + .build(); + + db = Nitrite.builder() + .loadModule(module(mapper)) + .loadModule(storeModule) + .fieldSeparator(".") + .openOrCreate(); + } + + @After + public void close() throws IOException { + db.close(); + db = null; + deleteDb(dbPath); + } + + @Test + public void testWithClassField() { + ObjectRepository repository = db.getRepository(WithClassField.class); + + WithClassField object = new WithClassField(); + object.setName("test"); + object.setClazz(String.class); + + repository.insert(object); + WithClassField instance = repository.getById("test"); + assertEquals(instance.getName(), object.getName()); + assertEquals(instance.getClazz(), object.getClazz()); + } + + @Test + public void testWithFinalField() { + ObjectRepository repository = db.getRepository(WithFinalField.class); + WithFinalField object = new WithFinalField(); + object.setName("test"); + + repository.insert(object); + for (WithFinalField instance : repository.find()) { + assertEquals(object.getName(), instance.getName()); + assertEquals(object.getNumber(), instance.getNumber()); + } + } + + @Test + public void testWithOutGetterSetter() { + ObjectRepository repository = db.getRepository(WithOutGetterSetter.class); + WithOutGetterSetter object = new WithOutGetterSetter(); + + repository.insert(object); + for (WithOutGetterSetter instance : repository.find()) { + assertEquals(object, instance); + } + } + + @Test + public void testWithOutId() { + ObjectRepository repository = db.getRepository(WithOutId.class); + WithOutId object = new WithOutId(); + object.setName("test"); + object.setNumber(2); + + repository.insert(object); + for (WithOutId instance : repository.find()) { + assertEquals(object.getName(), instance.getName()); + assertEquals(object.getNumber(), instance.getNumber()); + } + } + + @Test + public void testWithPublicField() { + ObjectRepository repository = db.getRepository(WithPublicField.class); + WithPublicField object = new WithPublicField(); + object.name = "test"; + object.number = 2; + + repository.insert(object); + WithPublicField instance = repository.getById("test"); + assertEquals(object.name, instance.name); + assertEquals(object.number, instance.number); + } + + @Test + public void testWithTransientField() { + ObjectRepository repository = db.getRepository(WithTransientField.class); + WithTransientField object = new WithTransientField(); + object.setNumber(2); + object.setName("test"); + + repository.insert(object); + WithTransientField instance = repository.getById(2L); + assertNotEquals(object.getName(), instance.getName()); + assertNull(instance.getName()); + assertEquals(object.getNumber(), instance.getNumber()); + } + + @Test + public void testWriteThousandRecords() { + int count = 5000; + + ObjectRepository repository = db.getRepository(StressRecord.class); + + for (int i = 0; i < count; i++) { + StressRecord record = new StressRecord(); + record.setFirstName(UUID.randomUUID().toString()); + record.setFailed(false); + record.setLastName(UUID.randomUUID().toString()); + record.setProcessed(false); + + repository.insert(record); + } + + Cursor cursor + = repository.find(where("failed").eq(false)); + + for (StressRecord record : cursor) { + record.setProcessed(true); + repository.update(where("firstName").eq(record.getFirstName()), record); + } + } + + @Test + public void testWithPackagePrivateClass() { + ObjectRepository repository = db.getRepository(InternalClass.class); + InternalClass internalClass = new InternalClass(); + internalClass.setId(1); + internalClass.setName("name"); + + repository.insert(internalClass); + InternalClass instance = repository.getById((long) 1); + assertEquals(internalClass.getName(), instance.getName()); + assertEquals(internalClass.getId(), instance.getId()); + } + + @Test + public void testWithPrivateConstructor() { + ObjectRepository repository = + db.getRepository(WithPrivateConstructor.class); + + WithPrivateConstructor object = WithPrivateConstructor.create("test", 2L); + repository.insert(object); + for (WithPrivateConstructor instance : repository.find()) { + assertEquals(object, instance); + } + } + + @Test + public void testWithDateAsId() { + ObjectRepository repository = db.getRepository(WithDateId.class); + + WithDateId object1 = new WithDateId(); + object1.setId(new Date(1482773634L)); + object1.setName("first date"); + repository.insert(object1); + + WithDateId object2 = new WithDateId(); + object2.setName("second date"); + object2.setId(new Date(1482773720L)); + repository.insert(object2); + + assertEquals(repository.find(where("id").eq(new Date(1482773634L))) + .firstOrNull(), object1); + assertEquals(repository.find(where("id").eq(new Date(1482773720L))) + .firstOrNull(), object2); + } + + @Test + public void testWithIdInheritance() { + ObjectRepository repository = db.getRepository(ChildClass.class); + assertTrue(repository.hasIndex("id")); + assertTrue(repository.hasIndex("date")); + assertTrue(repository.hasIndex("text")); + + ChildClass childClass = new ChildClass(); + childClass.setName("first"); + childClass.setDate(new Date(100000L)); + childClass.setId(1L); + childClass.setText("I am first class"); + repository.insert(childClass); + + childClass = new ChildClass(); + childClass.setName("seconds"); + childClass.setDate(new Date(100001L)); + childClass.setId(2L); + childClass.setText("I am second class"); + repository.insert(childClass); + + childClass = new ChildClass(); + childClass.setName("third"); + childClass.setDate(new Date(100002L)); + childClass.setId(3L); + childClass.setText("I am third class"); + repository.insert(childClass); + + assertEquals(repository.find(where("text").text("class")).size(), 3); + assertEquals(repository.find(where("text").text("second")).size(), 0); // filtered in stop words + assertEquals(repository.find(where("date").eq(new Date(100000L))).size(), 1); + assertEquals(repository.find(where("id").eq(1L)).size(), 1); + } + + @Test + public void testAttributes() { + ObjectRepository repository = db.getRepository(WithDateId.class); + Attributes attributes = new Attributes(repository.getDocumentCollection().getName()); + repository.setAttributes(attributes); + assertEquals(repository.getAttributes(), attributes); + } + + @Test + public void testKeyedRepository() { + // an object repository of employees who are managers + ObjectRepository managerRepo = db.getRepository(Employee.class, "managers"); + + // an object repository of all employee + ObjectRepository employeeRepo = db.getRepository(Employee.class); + + // and object repository of employees who are developers + ObjectRepository developerRepo = db.getRepository(Employee.class, "developers"); + + Employee manager = new Employee(); + manager.setEmpId(1L); + manager.setAddress("abcd"); + manager.setJoinDate(new Date()); + + Employee developer = new Employee(); + developer.setEmpId(2L); + developer.setAddress("xyz"); + developer.setJoinDate(new Date()); + + managerRepo.insert(manager); + employeeRepo.insert(manager, developer); + developerRepo.insert(developer); + + assertTrue(db.hasRepository(Employee.class)); + assertTrue(db.hasRepository(Employee.class, "managers")); + assertTrue(db.hasRepository(Employee.class, "developers")); + + assertEquals(db.listRepositories().size(), 1); + assertEquals(db.listKeyedRepository().size(), 2); + + assertEquals(employeeRepo.find(where("address").text("abcd")).size(), 1); + assertEquals(employeeRepo.find(where("address").text("xyz")).size(), 1); + assertEquals(managerRepo.find(where("address").text("xyz")).size(), 0); + assertEquals(managerRepo.find(where("address").text("abcd")).size(), 1); + assertEquals(developerRepo.find(where("address").text("xyz")).size(), 1); + assertEquals(developerRepo.find(where("address").text("abcd")).size(), 0); + } + + @Test + public void testEntityRepository() { + ObjectRepository managerRepo = db.getRepository(EmployeeEntity.class, "managers"); + ObjectRepository employeeRepo = db.getRepository(EmployeeEntity.class); + ObjectRepository developerRepo = db.getRepository(EmployeeEntity.class, "developers"); + + managerRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); + employeeRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); + developerRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); + + boolean errored = false; + try { + NitriteCollection collection = db.getCollection("entity.employee"); + } catch (ValidationException e) { + errored = true; + } + assertTrue(errored); + + assertTrue(db.listRepositories().contains("entity.employee")); + assertEquals(db.listKeyedRepository().size(), 2); + assertEquals(db.listCollectionNames().size(), 0); + + assertTrue(managerRepo.hasIndex("firstName")); + assertTrue(managerRepo.hasIndex("lastName")); + assertTrue(employeeRepo.hasIndex("lastName")); + assertTrue(employeeRepo.hasIndex("lastName")); + + managerRepo.drop(); + assertEquals(db.listKeyedRepository().size(), 1); + } + + @Test + public void testIssue217() { + ObjectRepository employeeRepo = db.getRepository(EmployeeEntity.class); + AtomicInteger counter = new AtomicInteger(0); + employeeRepo.subscribe(eventInfo -> counter.incrementAndGet()); + + ObjectRepository employeeRepo2 = db.getRepository(EmployeeEntity.class); + employeeRepo2.insert(new EmployeeEntity()); + await().atMost(5, TimeUnit.SECONDS).until(() -> counter.get() == 1); + } + + @Data + @Entity(value = "entity.employee", indices = { + @Index(value = "firstName", type = IndexType.NON_UNIQUE), + @Index(value = "lastName", type = IndexType.NON_UNIQUE), + }) + private static class EmployeeEntity implements Mappable { + private static final Faker faker = new Faker(); + + @Id + private Long id; + private String firstName; + private String lastName; + + public EmployeeEntity() { + id = faker.number().randomNumber(); + firstName = faker.name().firstName(); + lastName = faker.name().lastName(); + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("id", id) + .put("firstName", firstName) + .put("lastName", lastName); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Long.class); + firstName = document.get("firstName", String.class); + lastName = document.get("lastName", String.class); + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/ProjectionTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/ProjectionTest.java new file mode 100644 index 000000000..c6a85b0a3 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/ProjectionTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.integration.repository.data.SubEmployee; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.junit.Test; + +import java.util.Iterator; + +import static org.dizitart.no2.collection.FindOptions.skipBy; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class ProjectionTest extends BaseObjectRepositoryTest { + + @Test + public void testHasMore() { + RecordStream iterable = employeeRepository.find(skipBy(0).limit(5)) + .project(SubEmployee.class); + assertFalse(iterable.isEmpty()); + } + + @Test + public void testSize() { + RecordStream iterable = employeeRepository.find(skipBy(0).limit(5)) + .project(SubEmployee.class); + assertEquals(iterable.size(), 5); + } + + @Test + public void testToString() { + RecordStream iterable = employeeRepository.find(skipBy(0).limit(5)) + .project(SubEmployee.class); + assertNotNull(iterable.toString()); + } + + @Test(expected = InvalidOperationException.class) + public void testRemove() { + RecordStream iterable = employeeRepository.find(skipBy(0).limit(5)) + .project(SubEmployee.class); + Iterator iterator = iterable.iterator(); + if (iterator.hasNext()) { + iterator.next(); + iterator.remove(); + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryCompoundIndexTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryCompoundIndexTest.java new file mode 100644 index 000000000..9431d991e --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryCompoundIndexTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.integration.repository.data.Book; +import org.dizitart.no2.integration.repository.data.BookId; +import org.junit.Test; + +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee + */ +public class RepositoryCompoundIndexTest extends BaseObjectRepositoryTest { + + @Test + public void testFindById() { + BookId bookId = new BookId(); + bookId.setAuthor("John Doe"); + bookId.setIsbn("123456"); + bookId.setName("Nitrite Database"); + + Book book = new Book(); + book.setBookId(bookId); + book.setDescription("Some random book description"); + book.setPrice(22.56); + book.setPublisher("My Publisher House"); + book.setTags(Arrays.asList("database", "nosql")); + + bookRepository.insert(book); + + Book bookById = bookRepository.getById(bookId); + assertEquals(bookById, book); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryFactoryTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryFactoryTest.java new file mode 100644 index 000000000..d617767c0 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryFactoryTest.java @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.*; +import org.dizitart.no2.collection.events.CollectionEventListener; +import org.dizitart.no2.collection.meta.Attributes; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.common.concurrent.LockService; +import org.dizitart.no2.common.processors.Processor; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.integration.TestUtil; +import org.dizitart.no2.repository.RepositoryFactory; +import org.dizitart.no2.store.NitriteStore; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.util.Collection; + +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.assertNotNull; + +/** + * @author Anindya Chatterjee + */ +public class RepositoryFactoryTest { + private Nitrite db; + private final String fileName = getRandomTempDbFile(); + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + db = TestUtil.createDb(fileName); + } + + @Test + public void testRepositoryFactory() { + RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); + assertNotNull(factory); + } + + @Test(expected = ValidationException.class) + public void testNullType() { + RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); + factory.getRepository(db.getConfig(), null, "dummy"); + } + + @Test + public void testNullCollection() { + RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); + factory.getRepository(db.getConfig(), DummyCollection.class, null); + } + + @Test(expected = ValidationException.class) + public void testNullContext() { + RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); + factory.getRepository(null, DummyCollection.class, "dummy"); + } + + @After + public void cleanUp() { + if (db != null && !db.isClosed()) { + db.close(); + } + TestUtil.deleteDb(fileName); + } + + private static class DummyCollection implements NitriteCollection { + + @Override + public WriteResult insert(Document document, Document... documents) { + return null; + } + + @Override + public WriteResult update(Filter filter, Document update, UpdateOptions updateOptions) { + return null; + } + + @Override + public WriteResult remove(Filter filter, boolean justOne) { + return null; + } + + @Override + public DocumentCursor find() { + return null; + } + + @Override + public DocumentCursor find(Filter filter) { + return null; + } + + @Override + public DocumentCursor find(Filter filter, FindOptions findOptions) { + return null; + } + + @Override + public Document getById(NitriteId nitriteId) { + return null; + } + + @Override + public String getName() { + return null; + } + + @Override + public void addProcessor(Processor processor) { + + } + + @Override + public void removeProcessor(Processor processor) { + + } + + @Override + public void createIndex(IndexOptions indexOptions, String... fields) { + + } + + @Override + public void rebuildIndex(String... fields) { + + } + + @Override + public Collection listIndices() { + return null; + } + + @Override + public boolean hasIndex(String... fields) { + return false; + } + + @Override + public boolean isIndexing(String... fields) { + return false; + } + + @Override + public void dropIndex(String... fields) { + + } + + @Override + public void dropAllIndices() { + + } + + @Override + public WriteResult insert(Document[] elements) { + return null; + } + + @Override + public WriteResult update(Document element, boolean insertIfAbsent) { + return null; + } + + @Override + public WriteResult remove(Document element) { + return null; + } + + @Override + public void clear() { + + } + + @Override + public void drop() { + + } + + @Override + public boolean isDropped() { + return false; + } + + @Override + public boolean isOpen() { + return false; + } + + @Override + public void close() { + + } + + @Override + public long size() { + return 0; + } + + @Override + public NitriteStore getStore() { + return null; + } + + @Override + public void subscribe(CollectionEventListener listener) { + + } + + @Override + public void unsubscribe(CollectionEventListener listener) { + + } + + @Override + public Attributes getAttributes() { + return null; + } + + @Override + public void setAttributes(Attributes attributes) { + + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryJoinTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryJoinTest.java new file mode 100644 index 000000000..4dacdbff8 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryJoinTest.java @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.Lookup; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Id; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.collection.FindOptions.skipBy; +import static org.dizitart.no2.filters.Filter.ALL; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class RepositoryJoinTest extends BaseObjectRepositoryTest { + private ObjectRepository personRepository; + private ObjectRepository
addressRepository; + + @Before + public void setUp() { + openDb(); + + personRepository = db.getRepository(Person.class); + addressRepository = db.getRepository(Address.class); + + for (int i = 0; i < 10; i++) { + Person person = new Person(); + person.setId(Integer.toString(i)); + person.setName("Person " + i); + personRepository.insert(person); + + Address address = new Address(); + address.setPersonId(Integer.toString(i)); + address.setStreet("Street address " + i); + addressRepository.insert(address); + + if (i == 5) { + Address address2 = new Address(); + address2.setPersonId(Integer.toString(i)); + address2.setStreet("Street address 2nd " + i); + addressRepository.insert(address2); + } + } + } + + @After + public void clear() throws Exception { + if (personRepository != null && !personRepository.isDropped()) { + personRepository.remove(ALL); + } + + if (addressRepository != null && !addressRepository.isDropped()) { + addressRepository.remove(ALL); + } + + super.clear(); + } + + @Test + public void testJoin() { + Lookup lookup = new Lookup(); + lookup.setLocalField("id"); + lookup.setForeignField("personId"); + lookup.setTargetField("addresses"); + + RecordStream result + = personRepository.find().join(addressRepository.find(), lookup, + PersonDetails.class); + assertEquals(result.size(), 10); + + for (PersonDetails personDetails : result) { + Address[] addresses = personDetails.addresses.toArray(new Address[0]); + if (personDetails.id.equals("5")) { + assertEquals(addresses.length, 2); + } else { + assertEquals(addresses.length, 1); + assertEquals(addresses[0].personId, personDetails.getId()); + } + } + + result = personRepository.find(skipBy(0).limit(5)).join(addressRepository.find(), lookup, + PersonDetails.class); + + assertEquals(result.size(), 5); + assertFalse(result.isEmpty()); + assertNotNull(result.toString()); + } + + @Test(expected = InvalidOperationException.class) + public void testRemove() { + Lookup lookup = new Lookup(); + lookup.setLocalField("id"); + lookup.setForeignField("personId"); + lookup.setTargetField("addresses"); + + RecordStream result + = personRepository.find().join(addressRepository.find(), lookup, + PersonDetails.class); + assertEquals(result.size(), 10); + + Iterator iterator = result.iterator(); + if (iterator.hasNext()) { + iterator.next(); + iterator.remove(); + } + } + + @Data + public static class Person implements Mappable { + @Id + private NitriteId nitriteId; + private String id; + private String name; + + @Override + public Document write(NitriteMapper mapper) { + return createDocument() + .put("nitriteId", nitriteId) + .put("id", id) + .put("name", name); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + nitriteId = document.get("nitriteId", NitriteId.class); + id = document.get("id", String.class); + name = document.get("name", String.class); + } + } + + @Data + public static class Address implements Mappable { + @Id + private NitriteId nitriteId; + private String personId; + private String street; + + @Override + public Document write(NitriteMapper mapper) { + return createDocument() + .put("nitriteId", nitriteId) + .put("personId", personId) + .put("street", street); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + nitriteId = document.get("nitriteId", NitriteId.class); + personId = document.get("personId", String.class); + street = document.get("street", String.class); + } + } + + @Data + public static class PersonDetails implements Mappable { + @Id + private NitriteId nitriteId; + private String id; + private String name; + private List
addresses; + + @Override + public Document write(NitriteMapper mapper) { + return createDocument() + .put("nitriteId", nitriteId) + .put("personId", id) + .put("street", name) + .put("addresses", addresses); + } + + @Override + @SuppressWarnings("unchecked") + public void read(NitriteMapper mapper, Document document) { + nitriteId = document.get("nitriteId", NitriteId.class); + id = document.get("id", String.class); + name = document.get("name", String.class); + Set documents = document.get("addresses", Set.class); + this.addresses = new ArrayList<>(); + for (Document doc : documents) { + Address address = new Address(); + address.read(mapper, doc); + addresses.add(address); + } + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryModificationTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryModificationTest.java new file mode 100644 index 000000000..d5bd0f5cb --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryModificationTest.java @@ -0,0 +1,657 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.integration.repository.data.*; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.exceptions.InvalidIdException; +import org.dizitart.no2.exceptions.UniqueConstraintException; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.Test; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Date; +import java.util.Locale; + +import static org.awaitility.Awaitility.await; +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + + +/** + * @author Anindya Chatterjee. + */ +public class RepositoryModificationTest extends BaseObjectRepositoryTest { + + @Test + public void testCreateIndex() { + assertTrue(companyRepository.hasIndex("companyName")); + assertFalse(companyRepository.hasIndex("dateCreated")); + + companyRepository.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "dateCreated"); + assertTrue(companyRepository.hasIndex("dateCreated")); + assertFalse(companyRepository.isIndexing("dateCreated")); + } + + @Test + public void testRebuildIndex() { + companyRepository.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "dateCreated"); + assertFalse(companyRepository.isIndexing("dateCreated")); + + companyRepository.rebuildIndex("dateCreated"); + // rebuild is sync + assertFalse(companyRepository.isIndexing("dateCreated")); + + await().until(() -> !companyRepository.isIndexing("dateCreated")); + } + + @Test + public void testListIndexes() { + Collection indices = companyRepository.listIndices(); + assertEquals(indices.size(), 2); + + companyRepository.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "dateCreated"); + indices = companyRepository.listIndices(); + assertEquals(indices.size(), 3); + } + + @Test + public void testDropIndex() { + testListIndexes(); + companyRepository.dropIndex("dateCreated"); + Collection indices = companyRepository.listIndices(); + assertEquals(indices.size(), 2); + } + + @Test + public void testDropAllIndex() { + testListIndexes(); + companyRepository.dropAllIndices(); + Collection indices = companyRepository.listIndices(); + assertEquals(indices.size(), 0); + } + + @Test + public void testCompanyRecord() { + Cursor cursor = companyRepository.find(); + assertEquals(cursor.size(), 10); + assertFalse(cursor.isEmpty()); + } + + @Test + public void testInsert() { + Company company = DataGenerator.generateCompanyRecord(); + Cursor cursor = companyRepository.find(); + assertEquals(cursor.size(), 10); + + companyRepository.insert(company); + cursor = companyRepository.find(); + assertEquals(cursor.size(), 11); + + Company company1 = DataGenerator.generateCompanyRecord(); + Company company2 = DataGenerator.generateCompanyRecord(); + companyRepository.insert(new Company[]{company1, company2}); + cursor = companyRepository.find(); + assertEquals(cursor.size(), 13); + } + + @Test + public void testUpdateWithFilter() { + employeeRepository.remove(Filter.ALL); + + Employee employee = new Employee(); + employee.setCompany(null); + employee.setAddress("abcd road"); + employee.setBlob(new byte[]{1, 2, 125}); + employee.setEmpId(12L); + employee.setJoinDate(new Date()); + Note empNote = new Note(); + empNote.setNoteId(23L); + empNote.setText("sample text note"); + employee.setEmployeeNote(empNote); + + employeeRepository.insert(employee); + Cursor result = employeeRepository.find(); + assertEquals(result.size(), 1); + for (Employee e : result) { + assertEquals(e.getAddress(), "abcd road"); + } + + Employee updated = new Employee(employee); + updated.setAddress("xyz road"); + WriteResult writeResult = employeeRepository.update(where("empId").eq(12L), updated); + assertEquals(writeResult.getAffectedCount(), 1); + result = employeeRepository.find(); + assertEquals(result.size(), 1); + for (Employee e : result) { + assertEquals(e.getAddress(), "xyz road"); + } + } + + @Test + public void testUpdateWithJustOnceFalse() throws ParseException { + Date joiningDate = new Date(); + prepareUpdateWithOptions(joiningDate); + + SimpleDateFormat simpleDateFormat + = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); + Date newJoiningDate = simpleDateFormat.parse("2012-07-01T16:02:48.440Z"); + + Document updated1 = createDocument(); + updated1.put("joinDate", newJoiningDate); + + WriteResult writeResult + = employeeRepository.update(where("empId").eq(12L), updated1, false); + assertEquals(writeResult.getAffectedCount(), 1); + + Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 1); + result = employeeRepository.find(where("joinDate").eq(newJoiningDate)); + assertEquals(result.size(), 1); + + employeeRepository.remove(Filter.ALL); + prepareUpdateWithOptions(joiningDate); + result = employeeRepository.find(); + assertEquals(result.size(), 2); + + Document update = createDocument(); + update.put("joinDate", newJoiningDate); + + writeResult = employeeRepository.update(where("joinDate").eq(joiningDate), update, false); + assertEquals(writeResult.getAffectedCount(), 2); + + result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 0); + + result = employeeRepository.find(where("joinDate").eq(newJoiningDate)); + assertEquals(result.size(), 2); + } + + @Test + public void testUpsertTrue() { + Date joiningDate = new Date(); + Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 0); + + Employee employee = new Employee(); + employee.setCompany(null); + employee.setAddress("some road"); + employee.setBlob(new byte[]{1, 2, 125}); + employee.setEmpId(12L); + employee.setJoinDate(joiningDate); + Note empNote1 = new Note(); + empNote1.setNoteId(23L); + empNote1.setText("sample text note"); + employee.setEmployeeNote(empNote1); + + WriteResult writeResult + = employeeRepository.update(where("empId").eq(12), employee, true); + assertEquals(writeResult.getAffectedCount(), 1); + + result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 1); + } + + @Test + public void testUpsertFalse() { + Date joiningDate = new Date(); + Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 0); + + Employee employee = new Employee(); + employee.setCompany(null); + employee.setAddress("some road"); + employee.setBlob(new byte[]{1, 2, 125}); + employee.setEmpId(12L); + employee.setJoinDate(joiningDate); + Note empNote1 = new Note(); + empNote1.setNoteId(23L); + empNote1.setText("sample text note"); + employee.setEmployeeNote(empNote1); + + WriteResult writeResult + = employeeRepository.update(where("empId").eq(12), employee, false); + assertEquals(writeResult.getAffectedCount(), 0); + + result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 0); + } + + @Test + public void testDeleteFilterAndWithOutOption() { + Date joiningDate = new Date(); + prepareUpdateWithOptions(joiningDate); + + Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 2); + + WriteResult writeResult = employeeRepository.remove(where("joinDate").eq(joiningDate)); + assertEquals(writeResult.getAffectedCount(), 2); + result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 0); + } + + @Test + public void testDeleteFilterAndWithOption() { + Date joiningDate = new Date(); + prepareUpdateWithOptions(joiningDate); + + Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 2); + + WriteResult writeResult = employeeRepository.remove(where("joinDate").eq(joiningDate), true); + assertEquals(writeResult.getAffectedCount(), 1); + result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 1); + } + + @Test + public void testEmployeeRecord() { + Iterable totalResult = employeeRepository.find(); + int occurrence = 0; + for (Employee employee : totalResult) { + if (employee.getEmployeeNote().getText().toLowerCase().contains("class aptent")) { + occurrence++; + } + } + + Cursor cursor = employeeRepository.find(where("employeeNote.text").text("Class aptent")); + assertEquals(cursor.size(), occurrence); + } + + @Test + public void testUpdateWithOptions() { + Employee employee = employeeRepository.find().firstOrNull(); + + Document update = createDocument(); + update.put("address", "new address"); + + WriteResult writeResult + = employeeRepository.update(where("empId").eq(employee.getEmpId()), update, false); + assertEquals(writeResult.getAffectedCount(), 1); + + Employee byId = employeeRepository.getById(employee.getEmpId()); + assertEquals(byId.getAddress(), "new address"); + assertEquals(byId.getEmpId(), employee.getEmpId()); + + update.put("address", "another address"); + employeeRepository.update(where("empId").eq(employee.getEmpId()), update); + + byId = employeeRepository.getById(employee.getEmpId()); + assertEquals(byId.getAddress(), "another address"); + assertEquals(byId.getEmpId(), employee.getEmpId()); + } + + @Test(expected = InvalidIdException.class) + public void testMultiUpdateWithObject() { + employeeRepository.remove(Filter.ALL); + + Date now = new Date(); + Employee employee1 = new Employee(); + employee1.setEmpId(1L); + employee1.setAddress("abcd"); + employee1.setJoinDate(now); + + Employee employee2 = new Employee(); + employee2.setEmpId(2L); + employee2.setAddress("xyz"); + employee2.setJoinDate(now); + employeeRepository.insert(employee1, employee2); + + Employee update = new Employee(); + update.setAddress("new address"); + + WriteResult writeResult + = employeeRepository.update(where("joinDate").eq(now), update, false); + assertEquals(writeResult.getAffectedCount(), 0); + } + + @Test + public void testUpdateNull() { + Employee employee = employeeRepository.find().firstOrNull(); + Employee newEmployee = new Employee(employee); + newEmployee.setJoinDate(null); + + Employee result = employeeRepository.find(where("empId").eq(employee.getEmpId())).firstOrNull(); + assertNotNull(result.getJoinDate()); + + WriteResult writeResult = employeeRepository.update(newEmployee, false); + assertEquals(writeResult.getAffectedCount(), 1); + + result = employeeRepository.find(where("empId").eq(employee.getEmpId())).firstOrNull(); + assertNull(result.getJoinDate()); + + // update with object filter and item and set id different + } + + @Test + public void testUpdateWithChangedId() { + Employee employee = employeeRepository.find().firstOrNull(); + Long oldId = employee.getEmpId(); + long count = employeeRepository.size(); + + Employee newEmployee = new Employee(employee); + newEmployee.setEmpId(50L); + + Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); + assertNotNull(result.getJoinDate()); + + WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); + assertEquals(writeResult.getAffectedCount(), 1); + + assertEquals(count, employeeRepository.size()); + Cursor cursor = employeeRepository.find(where("empId").eq(oldId)); + assertEquals(cursor.size(), 0); + } + + @Test(expected = InvalidIdException.class) + public void testUpdateWithNullId() { + Employee employee = employeeRepository.find().firstOrNull(); + Long oldId = employee.getEmpId(); + + Employee newEmployee = new Employee(employee); + newEmployee.setEmpId(null); + + Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); + assertNotNull(result.getJoinDate()); + + WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); + assertEquals(writeResult.getAffectedCount(), 1); + } + + @Test(expected = UniqueConstraintException.class) + public void testUpdateWithDuplicateId() { + Employee employee = employeeRepository.find().firstOrNull(); + Long oldId = employee.getEmpId(); + long count = employeeRepository.size(); + + Employee newEmployee = new Employee(employee); + newEmployee.setEmpId(5L); + + Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); + assertNotNull(result.getJoinDate()); + + WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); + assertEquals(writeResult.getAffectedCount(), 1); + + assertEquals(count, employeeRepository.size()); + Cursor cursor = employeeRepository.find(where("empId").eq(oldId)); + assertEquals(cursor.size(), 0); + } + + @Test + public void testUpdateWithObject() { + Employee employee = employeeRepository.find().firstOrNull(); + Employee newEmployee = new Employee(employee); + + Long id = employee.getEmpId(); + String address = employee.getAddress(); + newEmployee.setAddress("new address"); + + WriteResult writeResult = employeeRepository.update(newEmployee); + assertEquals(writeResult.getAffectedCount(), 1); + + Employee emp = employeeRepository.find(where("empId").eq(id)).firstOrNull(); + assertNotEquals(address, emp.getAddress()); + assertEquals(employee.getEmpId(), emp.getEmpId()); + assertEquals(employee.getJoinDate(), emp.getJoinDate()); + assertArrayEquals(employee.getBlob(), emp.getBlob()); + } + + @Test + public void testUpsertWithObject() { + Employee employee = new Employee(); + employee.setCompany(null); + employee.setAddress("some road"); + employee.setBlob(new byte[]{1, 2, 125}); + employee.setEmpId(12L); + employee.setJoinDate(new Date()); + Note empNote = new Note(); + empNote.setNoteId(23L); + empNote.setText("sample text note"); + employee.setEmployeeNote(empNote); + + WriteResult writeResult = employeeRepository.update(employee, false); + assertEquals(writeResult.getAffectedCount(), 0); + writeResult = employeeRepository.update(employee, true); + assertEquals(writeResult.getAffectedCount(), 1); + + Employee emp = employeeRepository.find(where("empId").eq(12L)).firstOrNull(); + assertEquals(emp, employee); + } + + @Test + public void testRemoveObject() { + Employee employee = new Employee(); + employee.setCompany(null); + employee.setAddress("some road"); + employee.setBlob(new byte[]{1, 2, 125}); + employee.setEmpId(12L); + employee.setJoinDate(new Date()); + Note empNote = new Note(); + empNote.setNoteId(23L); + empNote.setText("sample text note"); + employee.setEmployeeNote(empNote); + + long size = employeeRepository.size(); + + employeeRepository.insert(employee); + assertEquals(employeeRepository.size(), size + 1); + + employeeRepository.remove(employee); + assertEquals(employeeRepository.size(), size); + + Employee emp = employeeRepository.find(where("empId").eq(12L)).firstOrNull(); + assertNull(emp); + } + + private void prepareUpdateWithOptions(Date joiningDate) { + employeeRepository.remove(Filter.ALL); + + Employee employee1 = new Employee(); + employee1.setCompany(null); + employee1.setAddress("some road"); + employee1.setBlob(new byte[]{1, 2, 125}); + employee1.setEmpId(12L); + employee1.setJoinDate(joiningDate); + Note empNote1 = new Note(); + empNote1.setNoteId(23L); + empNote1.setText("sample text note"); + employee1.setEmployeeNote(empNote1); + + Employee employee2 = new Employee(); + employee2.setCompany(null); + employee2.setAddress("other road"); + employee2.setBlob(new byte[]{10, 12, 25}); + employee2.setEmpId(2L); + employee2.setJoinDate(joiningDate); + Note empNote2 = new Note(); + empNote2.setNoteId(2L); + empNote2.setText("some random note"); + employee2.setEmployeeNote(empNote2); + + employeeRepository.insert(employee1, employee2); + Cursor result = employeeRepository.find(); + assertEquals(result.size(), 2); + for (Employee e : result.project(Employee.class)) { + assertEquals(e.getJoinDate(), joiningDate); + } + } + + @Test + public void testUpdateWithDoc() { + Note note = new Note(); + note.setNoteId(10L); + note.setText("some note text"); + + Document document = createDocument("address", "some address") + .put("employeeNote", note); + + WriteResult result = employeeRepository.update(Filter.ALL, document); + assertEquals(result.getAffectedCount(), 10); + } + + @Test + public void testDeleteIteratorNPE() { + ObjectRepository notes = db.getRepository(Note.class); + Note one = new Note(); + one.setText("Jane"); + one.setNoteId(1L); + Note two = new Note(); + two.setText("Jill"); + two.setNoteId(2L); + + notes.insert(one, two); + + WriteResult writeResult = notes.remove(where("text").eq("Pete")); + for (NitriteId id : writeResult) { + assertNotNull(id); + } + } + + @Test + public void testDelete() { + ObjectRepository repo = db.getRepository(WithNitriteId.class); + WithNitriteId one = new WithNitriteId(); + one.setName("Jane"); + repo.insert(one); + + WithNitriteId note = repo.find().firstOrNull(); + repo.remove(note); + + assertNull(repo.getById(one.idField)); + } + + /* + * Upsert Use Cases + * + * 1. Object does not exists + * a. if upsert true, it will insert + * b. if upsert false, nothing happens + * 2. Object exists + * a. if upsert true, it will update, old id remains same + * b. if upsert false, it will update, old id remains same + * + * */ + + @Test + public void testUpdateObjectNotExistsUpsertTrue() { + ObjectRepository repo = db.getRepository(InternalClass.class); + InternalClass a = new InternalClass(); + a.setId(1); + a.setName("first"); + repo.insert(a); + + a = new InternalClass(); + a.setId(2); + a.setName("second"); + + // it will insert as new object + repo.update(a, true); + assertEquals(repo.size(), 2); + } + + @Test + public void testUpdateObjectNotExistsUpsertFalse() { + ObjectRepository repo = db.getRepository(InternalClass.class); + InternalClass a = new InternalClass(); + a.setId(1); + a.setName("first"); + repo.insert(a); + + a = new InternalClass(); + a.setId(2); + a.setName("second"); + + // no changes will happen to repository + repo.update(a, false); + assertEquals(repo.size(), 1); + assertEquals(repo.find().firstOrNull().getId(), 1); + assertEquals(repo.find().firstOrNull().getName(), "first"); + } + + @Test + public void testUpdateObjectExistsUpsertTrue() { + ObjectRepository repo = db.getRepository(InternalClass.class); + InternalClass a = new InternalClass(); + a.setId(1); + a.setName("first"); + repo.insert(a); + + a = new InternalClass(); + a.setId(1); + a.setName("second"); + + // update existing object, keep id same + repo.update(a, true); + assertEquals(repo.size(), 1); + assertEquals(repo.find().firstOrNull().getId(), 1); + assertEquals(repo.find().firstOrNull().getName(), "second"); + } + + @Test + public void testUpdateObjectExistsUpsertFalse() { + ObjectRepository repo = db.getRepository(InternalClass.class); + InternalClass a = new InternalClass(); + a.setId(1); + a.setName("first"); + repo.insert(a); + + a = new InternalClass(); + a.setId(1); + a.setName("second"); + + // update existing object, keep id same + repo.update(a, false); + assertEquals(repo.size(), 1); + assertEquals(repo.find().firstOrNull().getId(), 1); + assertEquals(repo.find().firstOrNull().getName(), "second"); + } + + @Test + public void testNestedUpdate() { + Employee employee = employeeRepository.getById(1L); + assertNotNull(employee); + + Note note = employee.getEmployeeNote(); + String text = note.getText(); + assertNotNull(text); + + Document update = createDocument("employeeNote.text", "some updated text"); + WriteResult writeResult = employeeRepository.update(where("empId").eq(1L), update, true); + assertEquals(1, writeResult.getAffectedCount()); + + employee = employeeRepository.getById(1L); + assertNotNull(employee); + + note = employee.getEmployeeNote(); + assertNotNull(note); + assertNotEquals(text, note.getText()); + assertEquals("some updated text", note.getText()); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositorySearchTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositorySearchTest.java new file mode 100644 index 000000000..68015c9f3 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositorySearchTest.java @@ -0,0 +1,609 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import lombok.Getter; +import org.dizitart.no2.integration.repository.data.*; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.exceptions.InvalidIdException; +import org.dizitart.no2.exceptions.NotIdentifiableException; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.Test; + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.List; + +import static org.dizitart.no2.collection.FindOptions.orderBy; +import static org.dizitart.no2.collection.FindOptions.skipBy; +import static org.dizitart.no2.filters.Filter.*; +import static org.dizitart.no2.filters.FluentFilter.$; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class RepositorySearchTest extends BaseObjectRepositoryTest { + @Test + public void testFindWithOptions() { + Cursor cursor = employeeRepository.find(skipBy(0).limit(1)); + assertEquals(cursor.size(), 1); + assertNotNull(cursor.firstOrNull()); + } + + @Test + public void testEmployeeProjection() { + List employeeList = employeeRepository.find().toList(); + List subEmployeeList + = employeeRepository.find().project(SubEmployee.class).toList(); + + assertNotNull(employeeList); + assertNotNull(subEmployeeList); + + assertTrue(employeeList.size() > 0); + assertTrue(subEmployeeList.size() > 0); + + assertEquals(employeeList.size(), subEmployeeList.size()); + + for (int i = 0; i < subEmployeeList.size(); i++) { + Employee employee = employeeList.get(i); + SubEmployee subEmployee = subEmployeeList.get(i); + + assertEquals(employee.getEmpId(), subEmployee.getEmpId()); + assertEquals(employee.getJoinDate(), subEmployee.getJoinDate()); + assertEquals(employee.getAddress(), subEmployee.getAddress()); + } + + Cursor cursor = employeeRepository.find(); + assertNotNull(cursor.firstOrNull()); + assertNotNull(cursor.toString()); + assertEquals(cursor.toList().size(), employeeList.size()); + assertNotNull(cursor.firstOrNull()); + assertEquals(cursor.toList().size(), employeeList.size()); + } + + @Test + public void testEmptyResultProjection() { + employeeRepository.remove(ALL); + assertNull(employeeRepository.find().firstOrNull()); + + assertNull(employeeRepository.find(where("empId").eq(-1)) + .firstOrNull()); + } + + @Test + public void testGetById() { + ObjectRepository empRepo = db.getRepository(Employee.class); + Employee e1 = DataGenerator.generateEmployee(); + Employee e2 = DataGenerator.generateEmployee(); + Employee e3 = DataGenerator.generateEmployee(); + Employee e4 = DataGenerator.generateEmployee(); + + e1.setEmpId(1000000L); + e2.setEmpId(2000000L); + e3.setEmpId(3000000L); + e4.setEmpId(4000000L); + + empRepo.insert(e1, e2, e3, e4); + + Employee byId = empRepo.getById(2000000L); + assertEquals(byId, e2); + } + + @Test(expected = NotIdentifiableException.class) + public void testGetByIdNoId() { + ObjectRepository repository = db.getRepository(Note.class); + Note n1 = DataGenerator.randomNote(); + Note n2 = DataGenerator.randomNote(); + Note n3 = DataGenerator.randomNote(); + + n1.setNoteId(1000000L); + n2.setNoteId(2000000L); + n3.setNoteId(3000000L); + + repository.insert(n1, n2, n3); + + repository.getById(2000000L); + } + + @Test(expected = InvalidIdException.class) + public void testGetByIdNullId() { + ObjectRepository empRepo = db.getRepository(Employee.class); + Employee e1 = DataGenerator.generateEmployee(); + Employee e2 = DataGenerator.generateEmployee(); + Employee e3 = DataGenerator.generateEmployee(); + Employee e4 = DataGenerator.generateEmployee(); + + e1.setEmpId(1000000L); + e2.setEmpId(2000000L); + e3.setEmpId(3000000L); + e4.setEmpId(4000000L); + + empRepo.insert(e1, e2, e3, e4); + + empRepo.getById(null); + } + + @Test(expected = InvalidIdException.class) + public void testGetByIdWrongType() { + ObjectRepository empRepo = db.getRepository(Employee.class); + Employee e1 = DataGenerator.generateEmployee(); + Employee e2 = DataGenerator.generateEmployee(); + Employee e3 = DataGenerator.generateEmployee(); + Employee e4 = DataGenerator.generateEmployee(); + + e1.setEmpId(1000000L); + e2.setEmpId(2000000L); + e3.setEmpId(3000000L); + e4.setEmpId(4000000L); + + empRepo.insert(e1, e2, e3, e4); + + Employee byId = empRepo.getById("employee"); + assertNull(byId); + } + + @Test + public void testEqualFilterById() { + Employee employee = employeeRepository.find().firstOrNull(); + long empId = employee.getEmpId(); + Employee emp = employeeRepository.find(where("empId").eq(empId)) + .project(Employee.class).firstOrNull(); + assertEquals(employee, emp); + } + + @Test + public void testEqualFilter() { + Employee employee = employeeRepository.find() + .firstOrNull(); + + Employee emp = employeeRepository.find(where("joinDate").eq(employee.getJoinDate())) + .project(Employee.class) + .firstOrNull(); + assertEquals(employee, emp); + } + + @Test + public void testStringEqualFilter() { + ObjectRepository repository = db.getRepository(ProductScore.class); + + ProductScore object = new ProductScore(); + object.setProduct("test"); + object.setScore(1); + repository.insert(object); + + object = new ProductScore(); + object.setProduct("test"); + object.setScore(2); + repository.insert(object); + + object = new ProductScore(); + object.setProduct("another-test"); + object.setScore(3); + repository.insert(object); + + assertEquals(repository.find(where("product").eq("test")).size(), 2); + } + + @Test + public void testAndFilter() { + Employee emp = employeeRepository.find().firstOrNull(); + + long id = emp.getEmpId(); + String address = emp.getAddress(); + Date joinDate = emp.getJoinDate(); + + Cursor cursor = employeeRepository.find( + and( + where("empId").eq(id), + where("address").regex(address), + where("joinDate").eq(joinDate) + ) + ); + Employee employee = cursor.firstOrNull(); + + assertEquals(emp, employee); + } + + @Test + public void testOrFilter() { + Employee emp = employeeRepository.find().firstOrNull(); + long id = emp.getEmpId(); + + Employee employee = employeeRepository.find( + or( + where("empId").eq(id), + where("address").text("n/a"), + where("joinDate").eq(null) + )).firstOrNull(); + + assertEquals(emp, employee); + } + + @Test + public void testNotFilter() { + Employee emp = employeeRepository.find().firstOrNull(); + long id = emp.getEmpId(); + + Employee employee = employeeRepository.find( + where("empId").eq(id).not()).firstOrNull(); + assertNotEquals(emp, employee); + } + + @Test + public void testGreaterFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Ascending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").gt(id)) + .toList(); + + assertFalse(employeeList.contains(emp)); + assertEquals(employeeList.size(), 9); + } + + @Test + public void testGreaterEqualFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Ascending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").gte(id)) + .toList(); + + assertTrue(employeeList.contains(emp)); + assertEquals(employeeList.size(), 10); + } + + @Test + public void testLesserThanFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Descending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").lt(id)) + .toList(); + + assertFalse(employeeList.contains(emp)); + assertEquals(employeeList.size(), 9); + } + + @Test + public void testLesserEqualFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Descending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").lte(id)) + .toList(); + + assertTrue(employeeList.contains(emp)); + assertEquals(employeeList.size(), 10); + } + + @Test + public void testTextFilter() { + Employee emp = employeeRepository.find().firstOrNull(); + String text = emp.getEmployeeNote().getText(); + + List employeeList = employeeRepository.find(where("employeeNote.text").text(text)) + .toList(); + + assertTrue(employeeList.contains(emp)); + } + + @Test + public void testRegexFilter() { + Cursor employees = employeeRepository.find(); + int count = employees.toList().size(); + + List employeeList = employeeRepository.find(where("emailAddress") + .regex("^[a-zA-Z0-9+_.-]+@[a-zA-Z0-9.-]+$")) + .toList(); + + assertEquals(employeeList.size(), count); + } + + @Test + public void testInFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Descending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").in(id, id - 1, id - 2)) + .toList(); + + assertTrue(employeeList.contains(emp)); + assertEquals(employeeList.size(), 3); + + employeeList = employeeRepository.find(where("empId").in(id - 1, id - 2)).toList(); + assertEquals(employeeList.size(), 2); + } + + @Test + public void testNotInFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Descending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").notIn(id, id - 1, id - 2)) + .toList(); + + assertFalse(employeeList.contains(emp)); + assertEquals(employeeList.size(), 7); + + employeeList = employeeRepository.find(where("empId").notIn(id - 1, id - 2)).toList(); + assertEquals(employeeList.size(), 8); + } + + @Test + public void testElemMatchFilter() { + final ProductScore score1 = new ProductScore("abc", 10); + final ProductScore score2 = new ProductScore("abc", 8); + final ProductScore score3 = new ProductScore("abc", 7); + final ProductScore score4 = new ProductScore("xyz", 5); + final ProductScore score5 = new ProductScore("xyz", 7); + final ProductScore score6 = new ProductScore("xyz", 8); + + ObjectRepository repository = db.getRepository(ElemMatch.class); + ElemMatch e1 = new ElemMatch() {{ + setId(1); + setStrArray(new String[]{"a", "b"}); + setProductScores(new ProductScore[]{score1, score4}); + }}; + ElemMatch e2 = new ElemMatch() {{ + setId(2); + setStrArray(new String[]{"d", "e"}); + setProductScores(new ProductScore[]{score2, score5}); + }}; + ElemMatch e3 = new ElemMatch() {{ + setId(3); + setStrArray(new String[]{"a", "f"}); + setProductScores(new ProductScore[]{score3, score6}); + }}; + + repository.insert(e1, e2, e3); + + List elements = repository.find( + where("productScores").elemMatch( + where("product").eq("xyz") + .and(where("score").gte(8)))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("score").lte(8).not())).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("product").eq("xyz") + .or(where("score").gte(8)))).toList(); + assertEquals(elements.size(), 3); + + elements = repository.find( + where("productScores").elemMatch( + where("product").eq("xyz"))).toList(); + assertEquals(elements.size(), 3); + + elements = repository.find( + where("productScores").elemMatch( + where("score").gte(10))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("score").gt(8))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("score").lt(7))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("score").lte(7))).toList(); + assertEquals(elements.size(), 3); + + elements = repository.find( + where("productScores").elemMatch( + where("score").in(7, 8))).toList(); + assertEquals(elements.size(), 2); + + elements = repository.find( + where("productScores").elemMatch( + where("score").notIn(7, 8))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("product").regex("xyz"))).toList(); + assertEquals(elements.size(), 3); + + elements = repository.find(where("strArray").elemMatch($.eq("a"))).toList(); + assertEquals(elements.size(), 2); + + elements = repository.find( + where("strArray").elemMatch( + $.eq("a") + .or($.eq("f") + .or($.eq("b"))).not())).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find(where("strArray").elemMatch($.gt("e"))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find(where("strArray").elemMatch($.gte("e"))).toList(); + assertEquals(elements.size(), 2); + + elements = repository.find(where("strArray").elemMatch($.lte("b"))).toList(); + assertEquals(elements.size(), 2); + + elements = repository.find(where("strArray").elemMatch($.lt("a"))).toList(); + assertEquals(elements.size(), 0); + + elements = repository.find(where("strArray").elemMatch($.in("a", "f"))).toList(); + assertEquals(elements.size(), 2); + + elements = repository.find(where("strArray").elemMatch($.regex("a"))).toList(); + assertEquals(elements.size(), 2); + } + + @Test + public void testFilterAll() { + ObjectRepository repository = db.getRepository(ElemMatch.class); + Cursor cursor = repository.find(ALL); + assertNotNull(cursor); + assertEquals(cursor.size(), 0); + + repository.insert(new ElemMatch()); + cursor = repository.find(ALL); + assertNotNull(cursor); + assertEquals(cursor.size(), 1); + } + + @Test(expected = FilterException.class) + public void testEqualsOnTextIndex() { + PersonEntity p1 = new PersonEntity("jhonny"); + PersonEntity p2 = new PersonEntity("jhonny"); + PersonEntity p3 = new PersonEntity("jhonny"); + + ObjectRepository repository = db.getRepository(PersonEntity.class); + repository.insert(p1); + repository.insert(p2); + repository.insert(p3); + + List sameNamePeople = repository.find(where("name").eq("jhonny")).toList(); + assertEquals(sameNamePeople.size(), 3); + + sameNamePeople = repository.find(where("name").eq("JHONNY")).toList(); + assertEquals(sameNamePeople.size(), 0); + + sameNamePeople = repository.find(where("name").text("jhonny")).toList(); + assertEquals(sameNamePeople.size(), 3); + + sameNamePeople = repository.find(where("name").text("JHONNY")).toList(); + assertEquals(sameNamePeople.size(), 3); + + sameNamePeople = repository.find(where("name").eq("jhon*")).toList(); + assertEquals(sameNamePeople.size(), 0); + + sameNamePeople = repository.find(where("name").text("jhon*")).toList(); + assertEquals(sameNamePeople.size(), 3); + } + + @Test + public void testIssue62() { + PersonEntity p1 = new PersonEntity("abcd"); + p1.setStatus("Married"); + + PersonEntity p2 = new PersonEntity("efgh"); + p2.setStatus("Married"); + + PersonEntity p3 = new PersonEntity("ijkl"); + p3.setStatus("Un-Married"); + + ObjectRepository repository = db.getRepository(PersonEntity.class); + repository.insert(p1); + repository.insert(p2); + repository.insert(p3); + + Filter married = where("status").eq("Married"); + + assertEquals(repository.find(married).size(), 2); + assertEquals(repository.find(married, orderBy("status", SortOrder.Descending)).size(), 2); + + assertEquals(repository.find(orderBy("status", SortOrder.Descending)).firstOrNull().getStatus(), "Un-Married"); + + assertEquals(repository.find(orderBy("status", SortOrder.Ascending)).size(), 3); + assertEquals(repository.find(orderBy("status", SortOrder.Ascending)).firstOrNull().getStatus(), "Married"); + } + + @Test + public void testRepeatableIndexAnnotation() { + ObjectRepository repo = db.getRepository(RepeatableIndexTest.class); + RepeatableIndexTest first = new RepeatableIndexTest(); + first.setAge(12); + first.setFirstName("fName"); + first.setLastName("lName"); + repo.insert(first); + + assertTrue(repo.hasIndex("firstName")); + assertTrue(repo.hasIndex("age")); + assertTrue(repo.hasIndex("lastName")); + + assertEquals(repo.find(where("age").eq(12)).firstOrNull(), first); + } + + @Test + public void testIdSet() { + Cursor employees = employeeRepository.find(orderBy("empId", SortOrder.Ascending)); + assertEquals(employees.size(), 10); + } + + @Test + public void testBetweenFilter() { + @Getter + class TestData implements Mappable { + private Date age; + + public TestData(Date age) { + this.age = age; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("age", age); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + age = document.get("age", Date.class); + } + } + + TestData data1 = new TestData(new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime()); + TestData data2 = new TestData(new GregorianCalendar(2021, Calendar.FEBRUARY, 12).getTime()); + TestData data3 = new TestData(new GregorianCalendar(2022, Calendar.MARCH, 13).getTime()); + TestData data4 = new TestData(new GregorianCalendar(2023, Calendar.APRIL, 14).getTime()); + TestData data5 = new TestData(new GregorianCalendar(2024, Calendar.MAY, 15).getTime()); + TestData data6 = new TestData(new GregorianCalendar(2025, Calendar.JUNE, 16).getTime()); + + ObjectRepository repository = db.getRepository(TestData.class); + repository.insert(data1, data2, data3, data4, data5, data6); + + Cursor cursor = repository.find(where("age").between( + new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), + new GregorianCalendar(2025, Calendar.JUNE, 16).getTime())); + assertEquals(cursor.size(), 6); + + cursor = repository.find(where("age").between( + new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), + new GregorianCalendar(2025, Calendar.JUNE, 16).getTime(), false)); + assertEquals(cursor.size(), 4); + + cursor = repository.find(where("age").between( + new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), + new GregorianCalendar(2025, Calendar.JUNE, 16).getTime(), false, true)); + assertEquals(cursor.size(), 5); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/UnAnnotatedObjectTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/UnAnnotatedObjectTest.java new file mode 100644 index 000000000..cf793fb10 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/UnAnnotatedObjectTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + + +import org.dizitart.no2.integration.repository.data.ClassA; +import org.dizitart.no2.integration.repository.data.ClassC; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.repository.Cursor; +import org.junit.Test; + +import static org.dizitart.no2.collection.FindOptions.orderBy; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +/** + * @author Anindya Chatterjee. + */ +public class UnAnnotatedObjectTest extends BaseObjectRepositoryTest { + + @Test + public void testFind() { + Cursor cursor = aObjectRepository.find(); + assertEquals(cursor.size(), 10); + assertFalse(cursor.isEmpty()); + + aObjectRepository.createIndex("b.number"); + + cursor = aObjectRepository.find(where("b.number").eq(160).not(), + orderBy("b.number", SortOrder.Ascending).skip(0).limit(10)); + + System.out.println("Available - " + !cursor.isEmpty()); + System.out.println("Total Size - " + cursor.size()); + + Iterable findRecord = cursor.project(ClassA.class); + for (ClassA classA : findRecord) { + System.out.println(classA); + } + + cursor = aObjectRepository.find(where("b.number").eq(160).not(), + orderBy("b.number", SortOrder.Descending).skip(2).limit(7)); + + System.out.println("Available - " + !cursor.isEmpty()); + System.out.println("Total Size - " + cursor.size()); + + findRecord = cursor.project(ClassA.class); + for (ClassA classA : findRecord) { + System.out.println(classA); + } + + cursor = cObjectRepository.find(where("id").gt(900), + orderBy("id", SortOrder.Descending).skip(2).limit(7)); + System.out.println("Available - " + !cursor.isEmpty()); + System.out.println("Total Size - " + cursor.size()); + + Iterable findRecordC = cursor.project(ClassC.class); + for (ClassC classC : findRecordC) { + System.out.println(classC); + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/UniversalTextTokenizerTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/UniversalTextTokenizerTest.java new file mode 100644 index 000000000..057a0b78e --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/UniversalTextTokenizerTest.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteBuilder; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.index.NitriteTextIndexer; +import org.dizitart.no2.index.fulltext.Languages; +import org.dizitart.no2.index.fulltext.UniversalTextTokenizer; +import org.dizitart.no2.mvstore.MVStoreModule; +import org.dizitart.no2.mvstore.MVStoreModuleBuilder; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Index; +import org.dizitart.no2.repository.annotations.Indices; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static org.dizitart.no2.common.module.NitriteModule.module; +import static org.dizitart.no2.filters.Filter.ALL; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +/** + * @author Anindya Chatterjee + */ +public class UniversalTextTokenizerTest extends BaseObjectRepositoryTest { + private final String fileName = getRandomTempDbFile(); + private ObjectRepository textRepository; + + @Before + @Override + public void setUp() { + openDb(); + + textRepository = db.getRepository(TextData.class); + + for (int i = 0; i < 10; i++) { + TextData data = new TextData(); + data.id = i; + if (i % 2 == 0) { + data.text = "তারা বলল, “এস আমরা আমাদের জন্যে এক বড় শহর বানাই| আর এমন একটি উঁচু স্তম্ভ বানাই " + + "যা আকাশ স্পর্শ করবে| তাহলে আমরা বিখ্যাত হব এবং এটা আমাদের এক সঙ্গে ধরে রাখবে| সারা পৃথিবীতে " + + "আমরা ছড়িয়ে থাকব না|”"; + } else if (i % 3 == 0) { + data.text = "部汁楽示時葉没式将場参右属。覧観将者雄日語山銀玉襲政著約域費。新意虫跡更味株付安署審完顔団。" + + "困更表転定一史賀面政巣迎文学豊税乗。白間接特時京転閉務講封新内。側流効表害場測投活聞秀職探画労。" + + "福川順式極木注美込行警検直性禁遅。土一詳非物質紙姿漢人内池銀周街躍澹二。平討聞述並時全経詳業映回作朝送恵時。"; + } else if (i % 5 == 0) { + data.text = " أقبل لسفن العالم، في أما, بـ بال أملاً الثالث،. الذود بالرّد الثالث، مع" + + " قام, كردة الضغوط الإمداد أن وصل. ٠٨٠٤ عُقر انتباه يكن قد, أن زهاء وفنلندا بال. لان ما يقوم المعاهدات," + + " بـ بخطوط استعملت عدد. صفحة لفشل ولاتّساع لم قام, في مكثّفة الكونجرس جعل, الثالث، واقتصار دون ان.\n"; + } else { + data.text = "Lorem ipsum dolor sit amet, nobis audire perpetua eu sea. Te semper causae " + + "efficiantur per. Qui affert dolorum at. Mel tale constituto interesset in."; + } + textRepository.insert(data); + } + } + + @After + @Override + public void clear() throws Exception { + if (textRepository != null && !textRepository.isDropped()) { + textRepository.remove(ALL); + } + + if (db != null) { + db.commit(); + db.close(); + } + + if (!inMemory) { + deleteDb(fileName); + } + } + + @Override + protected void openDb() { + MVStoreModuleBuilder builder = MVStoreModule.withConfig(); + + if (isCompressed) { + builder.compress(true); + } + + if (!isAutoCommit) { + builder.autoCommit(false); + } + + if (!inMemory) { + builder.filePath(fileName); + } + + MVStoreModule storeModule = builder.build(); + NitriteBuilder nitriteBuilder = Nitrite.builder() + .fieldSeparator(".") + .loadModule(storeModule); + + UniversalTextTokenizer tokenizer; + if (isCompressed) { + tokenizer = new UniversalTextTokenizer(Languages.Bengali, Languages.Chinese, Languages.English); + } else { + tokenizer = new UniversalTextTokenizer(Languages.ALL); + } + nitriteBuilder.loadModule(module(new NitriteTextIndexer(tokenizer))); + + if (isProtected) { + db = nitriteBuilder.openOrCreate("test-user", "test-password"); + } else { + db = nitriteBuilder.openOrCreate(); + } + } + + @Test + public void testUniversalFullTextIndexing() { + Cursor cursor = textRepository.find(where("text").text("Lorem")); + assertEquals(cursor.size(), 2); + for (TextData data : cursor) { + System.out.println("Id for English text -> " + data.id); + if (data.id % 2 == 0 || data.id % 3 == 0 || data.id % 5 == 0) { + fail(); + } + } + + cursor = textRepository.find(where("text").text("শহর")); + assertEquals(cursor.size(), 5); + for (TextData data : cursor) { + System.out.println("Id for Bengali text -> " + data.id); + if (data.id % 2 != 0) { + fail(); + } + } + + cursor = textRepository.find(where("text").text("転閉")); + assertEquals(cursor.size(), 0); + cursor = textRepository.find(where("text").text("*転閉*")); + assertEquals(cursor.size(), 2); + for (TextData data : cursor) { + System.out.println("Id for Chinese text -> " + data.id); + if (data.id % 3 != 0) { + fail(); + } + } + + cursor = textRepository.find(where("text").text("أقبل")); + if (isCompressed) { + assertEquals(cursor.size(), 1); + for (TextData data : cursor) { + System.out.println("Id for Arabic text -> " + data.id); + if (data.id % 5 != 0) { + fail(); + } + } + } else { + // أقبل eliminated as stop word + assertEquals(cursor.size(), 0); + } + } + + @Indices( + @Index(value = "text", type = IndexType.FULL_TEXT) + ) + public static class TextData implements Mappable { + public int id; + public String text; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("id", id) + .put("text", text); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Integer.class); + text = document.get("text", String.class); + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Book.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Book.java new file mode 100644 index 000000000..5a147769c --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Book.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.repository.annotations.Entity; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +import java.util.List; + +import static org.dizitart.no2.collection.Document.createDocument; + +/** + * @author Anindya Chatterjee + */ +@Data +@Entity(value = "books", indices = { + @Index(value = "tags", type = IndexType.NON_UNIQUE), + @Index(value = "description", type = IndexType.FULL_TEXT), + @Index(value = { "price", "publisher" }) +}) +public class Book implements Mappable { + @Id(fieldName = "book_id") + private BookId bookId; + + private String publisher; + + private Double price; + + private List tags; + + private String description; + + @Override + public Document write(NitriteMapper mapper) { + return createDocument("book_id", mapper.convert(bookId, Document.class)) + .put("publisher", publisher) + .put("price", price) + .put("tags", tags) + .put("description", description); + } + + @Override + @SuppressWarnings("unchecked") + public void read(NitriteMapper mapper, Document document) { + bookId = mapper.convert(document.get("book_id"), BookId.class); + publisher = document.get("publisher", String.class); + price = document.get("price", Double.class); + tags = (List) document.get("tags", List.class); + description = document.get("description", String.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/BookId.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/BookId.java new file mode 100644 index 000000000..239b493d3 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/BookId.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Embedded; + +import static org.dizitart.no2.collection.Document.createDocument; + +/** + * @author Anindya Chatterjee + */ +@Data +public class BookId implements Mappable { + @Embedded(order = 0) + private String isbn; + + @Embedded(order = 1, fieldName = "book_name") + private String name; + + private String author; + + @Override + public Document write(NitriteMapper mapper) { + return createDocument("isbn", isbn) + .put("book_name", name) + .put("author", author); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + isbn = document.get("isbn", String.class); + name = document.get("book_name", String.class); + author = document.get("author", String.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ChildClass.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ChildClass.java new file mode 100644 index 000000000..d3c2ba644 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ChildClass.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.InheritIndices; + +/** + * @author Anindya Chatterjee + */ +@Getter +@Setter +@InheritIndices +public class ChildClass extends ParentClass { + private String name; + + @Override + public Document write(NitriteMapper mapper) { + return super.write(mapper).put("name", name); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + super.read(mapper, document); + name = document.get("name", String.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ClassA.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ClassA.java new file mode 100644 index 000000000..a8161c4e2 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ClassA.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +import java.util.UUID; + +@EqualsAndHashCode +@ToString +public class ClassA implements Mappable { + @Getter + @Setter + private ClassB b; + @Getter + @Setter + private UUID uid; + @Getter + @Setter + private String string; + @Getter + @Setter + private byte[] blob; + + public static ClassA create(int seed) { + ClassB classB = ClassB.create(seed); + ClassA classA = new ClassA(); + classA.b = classB; + classA.uid = new UUID(seed, seed + 50); + classA.string = Integer.toHexString(seed); + classA.blob = new byte[]{(byte) seed}; + return classA; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("b", b != null ? b.write(mapper) : null) + .put("uid", uid) + .put("string", string) + .put("blob", blob); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + if (document.get("b") != null) { + b = new ClassB(); + b.read(mapper, document.get("b", Document.class)); + } + uid = document.get("uid", UUID.class); + string = document.get("string", String.class); + blob = document.get("blob", byte[].class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ClassB.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ClassB.java new file mode 100644 index 000000000..a546b91e2 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ClassB.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +@EqualsAndHashCode +@ToString +class ClassB implements Comparable, Mappable { + @Getter + @Setter + private int number; + @Getter + @Setter + private String text; + + static ClassB create(int seed) { + ClassB classB = new ClassB(); + classB.setNumber(seed + 100); + classB.setText(Integer.toBinaryString(seed)); + return classB; + } + + @Override + public int compareTo(ClassB o) { + return Integer.compare(number, o.number); + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("number", number) + .put("text", text); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + number = document.get("number", Integer.class); + text = document.get("text", String.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ClassC.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ClassC.java new file mode 100644 index 000000000..860fe1e93 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ClassC.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +@EqualsAndHashCode +@ToString +public class ClassC implements Mappable { + @Getter + @Setter + private long id; + @Getter + @Setter + private double digit; + @Getter + @Setter + private ClassA parent; + + public static ClassC create(int seed) { + ClassC classC = new ClassC(); + classC.id = seed * 5000L; + classC.digit = seed * 69.65; + classC.parent = ClassA.create(seed); + return classC; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("id", id) + .put("digit", digit) + .put("parent", parent != null ? parent.write(mapper) : null); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Long.class); + digit = document.get("digit", Double.class); + if (document.get("parent") != null) { + parent = new ClassA(); + parent.read(mapper, document.get("parent", Document.class)); + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Company.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Company.java new file mode 100644 index 000000000..944e17358 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Company.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; +import org.dizitart.no2.repository.annotations.Indices; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @author Anindya Chatterjee. + */ +@EqualsAndHashCode +@Indices({ + @Index(value = "companyName") +}) +public class Company implements Serializable, Mappable { + @Id(fieldName = "company_id") + @Getter + @Setter + private Long companyId; + + @Getter + @Setter + private String companyName; + + @Getter + @Setter + private Date dateCreated; + + @Getter + @Setter + private List departments; + + @Getter + @Setter + private Map> employeeRecord; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("company_id", companyId) + .put("companyName", companyName) + .put("dateCreated", dateCreated) + .put("departments", departments) + .put("employeeRecord", employeeRecord); + } + + @Override + @SuppressWarnings("unchecked") + public void read(NitriteMapper mapper, Document document) { + companyId = document.get("company_id", Long.class); + companyName = document.get("companyName", String.class); + dateCreated = document.get("dateCreated", Date.class); + departments = document.get("departments", List.class); + employeeRecord = document.get("employeeRecord", Map.class); + } + + @Override + public String toString() { + return "Company{" + + "companyId=" + companyId + + ", companyName='" + companyName + '\'' + + ", dateCreated=" + dateCreated + + ", departments=" + departments + + '}'; + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/DataGenerator.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/DataGenerator.java new file mode 100644 index 000000000..26e0dcf4a --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/DataGenerator.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import com.github.javafaker.Faker; +import lombok.val; + +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author Anindya Chatterjee. + */ +public class DataGenerator { + private static final Random random = new Random(System.currentTimeMillis()); + private static final AtomicInteger counter = new AtomicInteger(random.nextInt()); + private static final Faker faker = new Faker(random); + + private DataGenerator() {} + + public static Company generateCompanyRecord() { + Company company = new Company(); + company.setCompanyId(System.nanoTime() + counter.incrementAndGet()); + company.setCompanyName(faker.company().name()); + company.setDateCreated(faker.date().past(10, TimeUnit.DAYS)); + List departments = departments(); + company.setDepartments(departments); + + Map> employeeRecord = new HashMap<>(); + for (String department : departments) { + employeeRecord.put(department, + generateEmployeeRecords(company, random.nextInt(20))); + } + company.setEmployeeRecord(employeeRecord); + return company; + } + + private static List generateEmployeeRecords(Company company, int count) { + List employeeList = new ArrayList<>(); + for (int i = 0; i < count; i++) { + Employee employee = generateEmployee(); + employee.setCompany(company); + employeeList.add(employee); + } + return employeeList; + } + + public static Employee generateEmployee() { + Employee employee = new Employee(); + employee.setEmpId(System.nanoTime() + counter.incrementAndGet()); + employee.setJoinDate(faker.date().birthday()); + employee.setAddress(faker.address().fullAddress()); + + employee.setBlob(faker.lorem().paragraph().getBytes(StandardCharsets.UTF_8)); + employee.setEmployeeNote(randomNote()); + employee.setEmailAddress(faker.internet().emailAddress()); + + return employee; + } + + public static Note randomNote() { + Note note = new Note(); + note.setNoteId(System.nanoTime() + counter.incrementAndGet()); + note.setText(faker.lorem().paragraph()); + return note; + } + + public static Book randomBook() { + BookId bookId = new BookId(); + val bookFaker = faker.book(); + bookId.setIsbn(faker.idNumber().ssnValid()); + bookId.setAuthor(bookFaker.author()); + bookId.setName(bookFaker.title()); + + Book book = new Book(); + book.setBookId(bookId); + book.setDescription(faker.backToTheFuture().quote()); + book.setPrice(faker.number().randomDouble(2, 100, 500)); + book.setPublisher(bookFaker.publisher()); + List tags = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + tags.add(bookFaker.genre()); + } + book.setTags(tags); + return book; + } + + private static List departments() { + return new ArrayList() {{ + add("dev"); + add("hr"); + add("qa"); + add("dev-ops"); + add("sales"); + add("marketing"); + add("design"); + add("support"); + }}; + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ElemMatch.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ElemMatch.java new file mode 100644 index 000000000..cb5304e29 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ElemMatch.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Anindya Chatterjee + */ +@Data +public class ElemMatch implements Mappable { + private long id; + private String[] strArray; + private ProductScore[] productScores; + + @Override + public Document write(NitriteMapper mapper) { + List list = new ArrayList<>(); + if (productScores != null) { + for (ProductScore productScore : productScores) { + Document document = productScore.write(mapper); + list.add(document); + } + } + + return Document.createDocument("id", id) + .put("strArray", strArray) + .put("productScores", list); + } + + @Override + @SuppressWarnings("unchecked") + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Long.class); + strArray = document.get("strArray", String[].class); + List list = document.get("productScores", List.class); + if (list != null) { + productScores = new ProductScore[list.size()]; + for (int i = 0; i < list.size(); i++) { + productScores[i] = new ProductScore(); + productScores[i].read(mapper, list.get(i)); + } + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Employee.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Employee.java new file mode 100644 index 000000000..7204f5654 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Employee.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author Anindya Chatterjee. + */ +@ToString +@EqualsAndHashCode +@Index(value = "joinDate", type = IndexType.NON_UNIQUE) +@Index(value = "address", type = IndexType.FULL_TEXT) +@Index(value = "employeeNote.text", type = IndexType.FULL_TEXT) +public class Employee implements Serializable, Mappable { + @Id + @Getter + @Setter + private Long empId; + + @Getter + @Setter + private Date joinDate; + + @Getter + @Setter + private String address; + + @Getter + @Setter + private String emailAddress; + + @Getter + @Setter + private transient Company company; + + @Getter + @Setter + private byte[] blob; + + @Getter + @Setter + private Note employeeNote; + + public Employee() { + } + + public Employee(Employee copy) { + empId = copy.empId; + joinDate = copy.joinDate; + address = copy.address; + company = copy.company; + blob = copy.blob; + employeeNote = copy.employeeNote; + emailAddress = copy.emailAddress; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("empId", empId) + .put("joinDate", joinDate) + .put("address", address) + .put("blob", blob) + .put("emailAddress", emailAddress) + .put("employeeNote", employeeNote != null ? employeeNote.write(mapper) : null); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + empId = document.get("empId", Long.class); + joinDate = document.get("joinDate", Date.class); + address = document.get("address", String.class); + blob = document.get("blob", byte[].class); + emailAddress = document.get("emailAddress", String.class); + + if (document.get("employeeNote") != null) { + employeeNote = new Note(); + employeeNote.read(mapper, document.get("employeeNote", Document.class)); + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/EncryptedPerson.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/EncryptedPerson.java new file mode 100644 index 000000000..8b9d4b23b --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/EncryptedPerson.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Entity; + +import java.util.Date; + +/** + * @author Anindya Chatterjee + */ +@Data +@Entity +public class EncryptedPerson implements Mappable { + private String name; + private String creditCardNumber; + private String cvv; + private Date expiryDate; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name) + .put("creditCardNumber", creditCardNumber) + .put("cvv", cvv) + .put("expiryDate", expiryDate); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + creditCardNumber = document.get("creditCardNumber", String.class); + cvv = document.get("cvv", String.class); + expiryDate = document.get("expiryDate", Date.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Note.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Note.java new file mode 100644 index 000000000..67dc307d1 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Note.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +import java.io.Serializable; + +/** + * @author Anindya Chatterjee. + */ +@EqualsAndHashCode +public class Note implements Serializable, Mappable { + @Getter + @Setter + private Long noteId; + @Getter + @Setter + private String text; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument().put("noteId", noteId).put("text", text); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + noteId = document.get("noteId", Long.class); + text = document.get("text", String.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ParentClass.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ParentClass.java new file mode 100644 index 000000000..bc2514543 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ParentClass.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +import java.util.Date; + +/** + * @author Anindya Chatterjee + */ +@Getter +@Setter +@Index(value = "date") +public class ParentClass extends SuperDuperClass { + @Id + protected Long id; + private Date date; + + @Override + public Document write(NitriteMapper mapper) { + return super.write(mapper) + .put("id", id) + .put("date", date); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + super.read(mapper, document); + id = document.get("id", Long.class); + date = document.get("date", Date.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/PersonEntity.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/PersonEntity.java new file mode 100644 index 000000000..2b90075fa --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/PersonEntity.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Entity; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +import java.util.Date; +import java.util.UUID; + +/** + * @author Anindya Chatterjee + */ +@Data +@Entity(value = "MyPerson", indices = { + @Index(value = "name", type = IndexType.FULL_TEXT), + @Index(value = "status", type = IndexType.NON_UNIQUE) +}) +public class PersonEntity implements Mappable { + @Id + private String uuid; + private String name; + private String status; + private PersonEntity friend; + private Date dateCreated; + + public PersonEntity() { + this.uuid = UUID.randomUUID().toString(); + this.dateCreated = new Date(); + } + + public PersonEntity(String name) { + this.uuid = UUID.randomUUID().toString(); + this.name = name; + this.dateCreated = new Date(); + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("uuid", uuid) + .put("name", name) + .put("status", status) + .put("friend", friend != null ? friend.write(mapper) : null) + .put("dateCreated", dateCreated); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + if (document != null) { + uuid = document.get("uuid", String.class); + name = document.get("name", String.class); + status = document.get("status", String.class); + dateCreated = document.get("dateCreated", Date.class); + friend = new PersonEntity(); + friend.read(mapper, document.get("friend", Document.class)); + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ProductScore.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ProductScore.java new file mode 100644 index 000000000..65550d182 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ProductScore.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +/** + * @author Anindya Chatterjee + */ +@Getter +@Setter +public class ProductScore implements Mappable { + private String product; + private int score; + + public ProductScore() { + } + + public ProductScore(String product, int score) { + this.product = product; + this.score = score; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("product", product) + .put("score", score); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + product = document.get("product", String.class); + score = document.get("score", Integer.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/RepeatableIndexTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/RepeatableIndexTest.java new file mode 100644 index 000000000..1ecadb243 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/RepeatableIndexTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Index; + +/** + * @author Anindya Chatterjee + */ +@Data +@Index(value = "firstName") +@Index(value = "age", type = IndexType.NON_UNIQUE) +@Index(value = "lastName", type = IndexType.FULL_TEXT) +public class RepeatableIndexTest implements Mappable { + private String firstName; + private Integer age; + private String lastName; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("firstName", firstName) + .put("age", age) + .put("lastName", lastName); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + firstName = document.get("firstName", String.class); + age = document.get("age", Integer.class); + lastName = document.get("lastName", String.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/StressRecord.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/StressRecord.java new file mode 100644 index 000000000..d1cb199c4 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/StressRecord.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class StressRecord implements Mappable { + private String firstName; + private boolean processed; + private String lastName; + private boolean failed; + private String notes; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument().put("firstName", firstName) + .put("processed", processed) + .put("lastName", lastName) + .put("failed", failed) + .put("notes", notes); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + firstName = document.get("firstName", String.class); + processed = document.get("processed", Boolean.class); + lastName = document.get("lastName", String.class); + failed = document.get("failed", Boolean.class); + notes = document.get("notes", String.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/SubEmployee.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/SubEmployee.java new file mode 100644 index 000000000..8eaa3faf1 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/SubEmployee.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +import java.util.Date; + +/** + * @author Anindya Chatterjee. + */ +@EqualsAndHashCode +public class SubEmployee implements Mappable { + @Getter + @Setter + private Long empId; + + @Getter + @Setter + private Date joinDate; + + @Getter + @Setter + private String address; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("empId", empId) + .put("joinDate", joinDate) + .put("address", address); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + empId = document.get("empId", Long.class); + joinDate = document.get("joinDate", Date.class); + address = document.get("address", String.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/SuperDuperClass.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/SuperDuperClass.java new file mode 100644 index 000000000..198f16d0c --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/SuperDuperClass.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Index; + +/** + * @author Anindya Chatterjee + */ +@Getter +@Setter +@Index(value = "text", type = IndexType.FULL_TEXT) +public class SuperDuperClass implements Mappable { + private String text; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("text", text); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + text = document.get("text", String.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithCircularReference.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithCircularReference.java new file mode 100644 index 000000000..efbb6766a --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithCircularReference.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithCircularReference { + private String name; + private WithCircularReference parent; +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithClassField.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithClassField.java new file mode 100644 index 000000000..79cafe0dc --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithClassField.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithClassField implements Mappable { + @Id + private String name; + private Class clazz; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name) + .put("clazz", clazz); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + clazz = document.get("clazz", Class.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithCustomConstructor.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithCustomConstructor.java new file mode 100644 index 000000000..bea5dabe9 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithCustomConstructor.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithCustomConstructor { + private String name; + private long number; + + public WithCustomConstructor(String name, long number) { + this.name = name; + this.number = number; + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithDateId.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithDateId.java new file mode 100644 index 000000000..229f1aaf7 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithDateId.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +import java.util.Date; + +/** + * @author Anindya Chatterjee + */ +@Getter +@Setter +@EqualsAndHashCode +public class WithDateId implements Mappable { + private Date id; + private String name; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name) + .put("id", id); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + id = document.get("id", Date.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithEmptyStringId.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithEmptyStringId.java new file mode 100644 index 000000000..a0048a6bb --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithEmptyStringId.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithEmptyStringId implements Mappable { + @Id + private String name; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithFinalField.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithFinalField.java new file mode 100644 index 000000000..05afc21e8 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithFinalField.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.exceptions.ObjectMappingException; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +/** + * @author Anindya Chatterjee. + */ +@Getter +public class WithFinalField implements Mappable { + private final long number; + @Setter + private String name; + + public WithFinalField() { + number = 2; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("name", name) + .put("number", number); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + try { + Field field = getClass().getDeclaredField("number"); + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(this, document.get("number", Long.class)); + } catch (Exception e) { + throw new ObjectMappingException("failed to set value"); + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithNitriteId.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithNitriteId.java new file mode 100644 index 000000000..2364be76d --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithNitriteId.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee + */ +@Data +public class WithNitriteId implements Mappable { + @Id + public NitriteId idField; + public String name; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("idField", idField) + .put("name", name); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + idField = document.get("idField", NitriteId.class); + name = document.get("name", String.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithNullId.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithNullId.java new file mode 100644 index 000000000..0dc3fb68b --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithNullId.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithNullId implements Mappable { + @Id + private String name; + private long number; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("name", name) + .put("number", number); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + number = document.get("number", Long.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithObjectId.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithObjectId.java new file mode 100644 index 000000000..5f00f97d4 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithObjectId.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithObjectId implements Mappable { + @Id + private WithOutId withOutId; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("withOutId", withOutId); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + withOutId = document.get("withOutId", WithOutId.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithOutGetterSetter.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithOutGetterSetter.java new file mode 100644 index 000000000..a7a2c56c9 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithOutGetterSetter.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +/** + * @author Anindya Chatterjee. + */ +@EqualsAndHashCode +public class WithOutGetterSetter implements Mappable { + private String name; + private long number; + + public WithOutGetterSetter() { + name = "test"; + number = 2; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name) + .put("number", number); + + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + number = document.get("number", Long.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithOutId.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithOutId.java new file mode 100644 index 000000000..09b63c2c2 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithOutId.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithOutId implements Comparable, Mappable { + private String name; + private long number; + + @Override + public int compareTo(WithOutId o) { + return Long.compare(number, o.number); + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("name", name) + .put("number", number); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + number = document.get("number", Long.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithPrivateConstructor.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithPrivateConstructor.java new file mode 100644 index 000000000..a425209fb --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithPrivateConstructor.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +/** + * @author Anindya Chatterjee. + */ +@EqualsAndHashCode +public class WithPrivateConstructor implements Mappable { + private String name; + private long number; + + private WithPrivateConstructor() { + name = "test"; + number = 2; + } + + public static WithPrivateConstructor create(final String name, final long number) { + WithPrivateConstructor obj = new WithPrivateConstructor(); + obj.number = number; + obj.name = name; + return obj; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name) + .put("number", number); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + number = document.get("number", Long.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithPublicField.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithPublicField.java new file mode 100644 index 000000000..793388231 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithPublicField.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +public class WithPublicField implements Mappable { + @Id + public String name; + public long number; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name) + .put("number", number); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + number = document.get("number", Long.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithTransientField.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithTransientField.java new file mode 100644 index 000000000..9c1ade657 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithTransientField.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithTransientField implements Mappable { + private transient String name; + @Id + private long number; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("number", number); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + number = document.get("number", Long.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithoutEmbeddedId.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithoutEmbeddedId.java new file mode 100644 index 000000000..9ecb9a68b --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithoutEmbeddedId.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee + */ +@Data +public class WithoutEmbeddedId implements Mappable { + @Id + private NestedId nestedId; + private String data; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("nestedId", nestedId.write(mapper)) + .put("data", data); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + Document nestedId = document.get("nestedId", Document.class); + this.nestedId = mapper.convert(nestedId, NestedId.class); + this.data = document.get("data", String.class); + } + + + @Data + public static class NestedId implements Mappable { + private Long id; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("id", id); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Long.class); + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/stream/DocumentCursorTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/stream/DocumentCursorTest.java new file mode 100644 index 000000000..de377b162 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/stream/DocumentCursorTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.stream; + +import org.dizitart.no2.integration.collection.BaseCollectionTest; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.streams.DocumentStream; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.junit.Test; + +import java.util.Iterator; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee. + */ +public class DocumentCursorTest extends BaseCollectionTest { + + @Test + public void testFindResult() { + NitriteCollection collection = db.getCollection("test"); + collection.insert(createDocument("first", "second")); + + DocumentCursor result = collection.find(); + assertTrue(result instanceof DocumentStream); + } + + @Test(expected = InvalidOperationException.class) + public void testIteratorRemove() { + NitriteCollection collection = db.getCollection("test"); + collection.insert(createDocument("first", "second")); + + DocumentCursor cursor = collection.find(); + Iterator iterator = cursor.iterator(); + if (iterator.hasNext()) { + iterator.next(); + iterator.remove(); + } + } + + @Test + public void testValidateProjection() { + NitriteCollection collection = db.getCollection("test"); + collection.insert(createDocument("first", "second")); + + Document projection = createDocument("first", createDocument("second", null)); + RecordStream project = collection.find().project(projection); + assertNotNull(project); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/stream/JoinedDocumentStreamTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/stream/JoinedDocumentStreamTest.java new file mode 100644 index 000000000..00923c738 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/stream/JoinedDocumentStreamTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.stream; + +import org.dizitart.no2.integration.collection.BaseCollectionTest; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.Lookup; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.streams.JoinedDocumentStream; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.junit.Test; + +import java.util.Iterator; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee + */ +public class JoinedDocumentStreamTest extends BaseCollectionTest { + + @Test + public void testFindResult() { + NitriteCollection collection = db.getCollection("test"); + collection.insert(createDocument("first", "second")); + + RecordStream result = collection.find().join(collection.find(), new Lookup()); + assertTrue(result instanceof JoinedDocumentStream); + } + + @Test(expected = InvalidOperationException.class) + public void testIteratorRemove() { + NitriteCollection collection = db.getCollection("test"); + collection.insert(createDocument("first", "second")); + + RecordStream cursor = collection.find().join(collection.find(), new Lookup()); + assertNotNull(cursor.toString()); + Iterator iterator = cursor.iterator(); + if (iterator.hasNext()) { + iterator.next(); + iterator.remove(); + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/transaction/TransactionCollectionTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/transaction/TransactionCollectionTest.java new file mode 100644 index 000000000..05a2b095b --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/transaction/TransactionCollectionTest.java @@ -0,0 +1,791 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.transaction; + +import com.github.javafaker.Faker; +import org.dizitart.no2.integration.collection.BaseCollectionTest; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.meta.Attributes; +import org.dizitart.no2.exceptions.NitriteIOException; +import org.dizitart.no2.exceptions.TransactionException; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.transaction.Session; +import org.dizitart.no2.transaction.Transaction; +import org.junit.Test; + +import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.collection.UpdateOptions.updateOptions; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class TransactionCollectionTest extends BaseCollectionTest { + + @Test + public void testCommitInsert() { + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + + Document document = createDocument("firstName", "John"); + txCol.insert(document); + + assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); + assertNotEquals(collection.find(where("firstName").eq("John")).size(), 1); + + transaction.commit(); + + assertEquals(collection.find(where("firstName").eq("John")).size(), 1); + } + } + } + + @Test + public void testRollbackInsert() { + collection.createIndex("firstName"); + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + + NitriteCollection txCol = transaction.getCollection("test"); + + Document document = createDocument("firstName", "John"); + Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); + txCol.insert(document); + txCol.insert(document2); + + // just to create UniqueConstraintViolation for rollback + collection.insert(createDocument("firstName", "Jane")); + + assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); + assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertNotEquals(collection.find(where("firstName").eq("John")).size(), 1); + assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + } + } + } + + @Test + public void testCommitUpdate() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + document.put("lastName", "Doe"); + + txCol.update(where("firstName").eq("John"), document, updateOptions(true)); + + assertEquals(txCol.find(where("lastName").eq("Doe")).size(), 1); + assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + + transaction.commit(); + + assertEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + } + } + } + + @Test + public void testRollbackUpdate() { + collection.createIndex("firstName"); + collection.insert(createDocument("firstName", "Jane")); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + + NitriteCollection txCol = transaction.getCollection("test"); + + Document document = createDocument("firstName", "John"); + Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); + txCol.update(where("firstName").eq("Jane"), document2); + txCol.insert(document); + + // just to create UniqueConstraintViolation for rollback + collection.insert(createDocument("firstName", "John")); + + assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); + assertEquals(txCol.find(where("lastName").eq("Doe")).size(), 1); + assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(collection.find(where("firstName").eq("Jane")).size(), 1); + assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + } + } + } + + @Test + public void testCommitRemove() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + + txCol.remove(where("firstName").eq("John")); + + assertEquals(txCol.find(where("firstName").eq("John")).size(), 0); + assertEquals(collection.find(where("firstName").eq("John")).size(), 1); + + transaction.commit(); + + assertEquals(collection.find(where("firstName").eq("John")).size(), 0); + } + } + } + + @Test + public void testRollbackRemove() { + collection.createIndex("firstName"); + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + NitriteCollection txCol = transaction.getCollection("test"); + + txCol.remove(where("firstName").eq("John")); + + assertEquals(txCol.find(where("firstName").eq("John")).size(), 0); + assertEquals(collection.find(where("firstName").eq("John")).size(), 1); + + txCol.insert(createDocument("firstName", "Jane")); + collection.insert(createDocument("firstName", "Jane")); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(collection.find(where("firstName").eq("John")).size(), 1); + assertEquals(collection.find(where("firstName").eq("Jane")).size(), 1); + } + } + } + + @Test + public void testCommitCreateIndex() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + txCol.createIndex(indexOptions(IndexType.FULL_TEXT), "firstName"); + + assertTrue(txCol.hasIndex("firstName")); + assertFalse(collection.hasIndex("firstName")); + + transaction.commit(); + + assertTrue(collection.hasIndex("firstName")); + } + } + } + + @Test + public void testRollbackCreateIndex() { + Document document = createDocument("firstName", "John"); + Document document2 = createDocument("firstName", "Jane"); + collection.insert(document); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + NitriteCollection txCol = transaction.getCollection("test"); + + txCol.createIndex("firstName"); + + assertTrue(txCol.hasIndex("firstName")); + assertFalse(collection.hasIndex("firstName")); + + txCol.insert(document2); + collection.insert(document2); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertFalse(collection.hasIndex("firstName")); + } + } + } + + @Test + public void testCommitClear() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + txCol.clear(); + + assertEquals(0, txCol.size()); + assertEquals(1, collection.size()); + + transaction.commit(); + + assertEquals(0, collection.size()); + } + } + } + + @Test + public void testRollbackClear() { + collection.createIndex("firstName"); + Document document = createDocument("firstName", "John"); + Document document2 = createDocument("firstName", "Jane"); + collection.insert(document); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + NitriteCollection txCol = transaction.getCollection("test"); + + txCol.clear(); + + assertEquals(0, txCol.size()); + assertEquals(1, collection.size()); + + txCol.insert(document2); + collection.insert(document2); + + throw new TransactionException("failed"); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(2, collection.size()); + } + } + } + + @Test + public void testCommitDropIndex() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + collection.createIndex("firstName"); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + txCol.dropIndex("firstName"); + + assertFalse(txCol.hasIndex("firstName")); + assertTrue(collection.hasIndex("firstName")); + + transaction.commit(); + + assertFalse(collection.hasIndex("firstName")); + } + } + } + + @Test + public void testRollbackDropIndex() { + Document document = createDocument("firstName", "John").put("lastName", "Doe"); + Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); + collection.insert(document); + collection.createIndex("firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + NitriteCollection txCol = transaction.getCollection("test"); + txCol.dropIndex("lastName"); + + assertFalse(txCol.hasIndex("lastName")); + assertTrue(collection.hasIndex("lastName")); + + txCol.insert(document2); + collection.insert(document2); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertTrue(collection.hasIndex("lastName")); + } + } + } + + @Test + public void testCommitDropAllIndices() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + collection.createIndex("firstName"); + collection.createIndex("lastName"); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + txCol.dropAllIndices(); + + assertFalse(txCol.hasIndex("firstName")); + assertFalse(txCol.hasIndex("lastName")); + assertTrue(collection.hasIndex("firstName")); + assertTrue(collection.hasIndex("lastName")); + + transaction.commit(); + + assertFalse(collection.hasIndex("firstName")); + assertFalse(collection.hasIndex("lastName")); + } + } + } + + @Test + public void testRollbackDropAllIndices() { + Document document = createDocument("firstName", "John").put("lastName", "Doe"); + collection.insert(document); + collection.createIndex("firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + NitriteCollection txCol = transaction.getCollection("test"); + txCol.dropAllIndices(); + + assertFalse(txCol.hasIndex("firstName")); + assertFalse(txCol.hasIndex("lastName")); + assertTrue(collection.hasIndex("firstName")); + assertTrue(collection.hasIndex("lastName")); + + txCol.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); + collection.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); + + throw new TransactionException("failed"); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertTrue(collection.hasIndex("firstName")); + assertTrue(collection.hasIndex("lastName")); + } + } + } + + @Test + public void testCommitDropCollection() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + txCol.drop(); + + boolean expectedException = false; + try { + assertEquals(0, txCol.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + assertEquals(1, collection.size()); + + transaction.commit(); + + expectedException = false; + try { + assertEquals(0, collection.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + } + } + } + + @Test + public void testRollbackDropCollection() { + collection.createIndex("firstName"); + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + NitriteCollection txCol = transaction.getCollection("test"); + + txCol.drop(); + + boolean expectedException = false; + try { + assertEquals(0, txCol.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + assertEquals(1, collection.size()); + + throw new TransactionException("failed"); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(1, collection.size()); + } + } + } + + @Test + public void testCommitSetAttribute() { + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + + Attributes attributes = new Attributes(); + Map hashMap = new HashMap<>(); + hashMap.put("key", "value"); + attributes.setAttributes(hashMap); + txCol.setAttributes(attributes); + + assertNull(collection.getAttributes()); + + transaction.commit(); + + assertEquals("value", collection.getAttributes().get("key")); + } + } + } + + @Test + public void testRollbackSetAttribute() { + collection.createIndex("firstName"); + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + + NitriteCollection txCol = transaction.getCollection("test"); + + Attributes attributes = new Attributes(); + Map map = new HashMap<>(); + map.put("key", "value"); + attributes.setAttributes(map); + txCol.setAttributes(attributes); + + txCol.insert(createDocument("firstName", "John")); + txCol.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); + + assertNull(collection.getAttributes()); + + // just to create UniqueConstraintViolation for rollback + collection.insert(createDocument("firstName", "Jane")); + + assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); + assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertNull(collection.getAttributes().get("key")); + } + } + } + + @Test + public void testConcurrentInsertAndRemove() { + NitriteCollection collection = db.getCollection("test"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "firstName"); + collection.createIndex("id"); + Faker faker = new Faker(); + List> futures = new ArrayList<>(); + + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + final long fi = i; + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + NitriteCollection txCol = transaction.getCollection("test"); + + for (int j = 0; j < 10; j++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("lastName", faker.name().lastName()) + .put("id", j + (fi * 10)); + txCol.insert(document); + } + + txCol.remove(where("id").eq(2 + (fi * 10))); + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(90, collection.size()); + } + } + + @Test + public void testConcurrentInsert() { + NitriteCollection collection = db.getCollection("test"); + Faker faker = new Faker(); + List> futures = new ArrayList<>(); + + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + NitriteCollection txCol = transaction.getCollection("test"); + + for (int j = 0; j < 10; j++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("lastName", faker.name().lastName()); + txCol.insert(document); + } + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(100, collection.size()); + } + } + + @Test + public void testConcurrentUpdate() { + NitriteCollection collection = db.getCollection("test"); + for (int i = 0; i < 10; i++) { + Document document = createDocument("id", i); + collection.insert(document); + } + + Faker faker = new Faker(); + List> futures = new ArrayList<>(); + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + NitriteCollection txCol = transaction.getCollection("test"); + + for (int j = 0; j < 10; j++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("lastName", faker.name().lastName()) + .put("id", j); + txCol.update(where("id").eq(j), document, updateOptions(true)); + } + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(10, collection.size()); + } + } + + @Test + public void testTransactionOnDifferentCollections() { + NitriteCollection col1 = db.getCollection("test1"); + NitriteCollection col2 = db.getCollection("test2"); + NitriteCollection col3 = db.getCollection("test3"); + col3.createIndex("id"); + + Faker faker = new Faker(); + + try(Session session = db.createSession()) { + Transaction transaction = session.beginTransaction(); + + NitriteCollection test1 = transaction.getCollection("test1"); + NitriteCollection test2 = transaction.getCollection("test2"); + NitriteCollection test3 = transaction.getCollection("test3"); + + for (int i = 0; i < 10; i++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", i); + test1.insert(document); + + document = createDocument("firstName", faker.name().firstName()) + .put("id", i + 10); + test2.insert(document); + + document = createDocument("firstName", faker.name().firstName()) + .put("id", i + 20); + test3.insert(document); + } + + assertEquals(test1.size(), 10); + assertEquals(test2.size(), 10); + assertEquals(test3.size(), 10); + + assertEquals(col1.size(), 0); + assertEquals(col2.size(), 0); + assertEquals(col3.size(), 0); + + transaction.commit(); + + assertEquals(col1.size(), 10); + assertEquals(col2.size(), 10); + assertEquals(col3.size(), 10); + } + + + Transaction transaction = null; + try (Session session = db.createSession()) { + transaction = session.beginTransaction(); + + NitriteCollection test1 = transaction.getCollection("test1"); + NitriteCollection test2 = transaction.getCollection("test2"); + NitriteCollection test3 = transaction.getCollection("test3"); + + for (int i = 0; i < 10; i++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", i + 30); + test1.insert(document); + + document = createDocument("firstName", faker.name().firstName()) + .put("id", i + 40); + test2.insert(document); + + document = createDocument("firstName", faker.name().firstName()) + .put("id", i + 50); + test3.insert(document); + } + + assertEquals(test1.size(), 20); + assertEquals(test2.size(), 20); + assertEquals(test3.size(), 20); + + assertEquals(col1.size(), 10); + assertEquals(col2.size(), 10); + assertEquals(col3.size(), 10); + + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", 52); + col3.insert(document); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + + assertEquals(col1.size(), 10); + assertEquals(col2.size(), 10); + assertEquals(col3.size(), 11); // last document added + } + } + + @Test(expected = TransactionException.class) + public void testFailureOnClosedTransaction() { + try(Session session = db.createSession()) { + Transaction transaction = session.beginTransaction(); + NitriteCollection col = transaction.getCollection("test"); + col.insert(createDocument("id", 1)); + transaction.commit(); + + col.insert(createDocument("id", 2)); + fail(); + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/transaction/TransactionRepositoryTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/transaction/TransactionRepositoryTest.java new file mode 100644 index 000000000..5e93303ed --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/transaction/TransactionRepositoryTest.java @@ -0,0 +1,829 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.transaction; + +import com.github.javafaker.Faker; +import org.dizitart.no2.integration.repository.BaseObjectRepositoryTest; +import org.dizitart.no2.integration.repository.data.SubEmployee; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.meta.Attributes; +import org.dizitart.no2.exceptions.NitriteIOException; +import org.dizitart.no2.exceptions.TransactionException; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.transaction.Session; +import org.dizitart.no2.transaction.Transaction; +import org.junit.Test; + +import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class TransactionRepositoryTest extends BaseObjectRepositoryTest { + + @Test + public void testCommitInsert() { + ObjectRepository repository = db.getRepository(TxData.class); + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + TxData txData1 = new TxData(); + txData1.setId(1L); + txData1.setName("John"); + + txRepo.insert(txData1); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 1); + assertNotEquals(repository.find(where("name").eq("John")).size(), 1); + + transaction.commit(); + + assertEquals(repository.find(where("name").eq("John")).size(), 1); + } + } + } + + @Test + public void testRollbackInsert() { + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + TxData txData1 = new TxData(); + txData1.setId(1L); + txData1.setName("John"); + + TxData txData2 = new TxData(); + txData2.setId(2L); + txData2.setName("Jane"); + + txRepo.insert(txData1, txData2); + + txData2.setName("Molly"); + repository.insert(txData2); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 1); + assertEquals(repository.find(where("name").eq("John")).size(), 0); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(repository.find(where("name").eq("John")).size(), 0); + assertEquals(repository.find(where("name").eq("Molly")).size(), 1); + } + } + } + + @Test + public void testCommitUpdate() { + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(new TxData(1L, "John")); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + TxData txData1 = new TxData(1L, "Jane"); + txRepo.update(txData1, true); + + assertEquals(txRepo.find(where("name").eq("Jane")).size(), 1); + assertNotEquals(repository.find(where("name").eq("Jane")).size(), 1); + + transaction.commit(); + + assertEquals(repository.find(where("name").eq("Jane")).size(), 1); + } + } + } + + @Test + public void testRollbackUpdate() { + ObjectRepository repository = db.getRepository(TxData.class, "rollback"); + repository.createIndex("name"); + repository.insert(new TxData(1L, "Jane")); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + + ObjectRepository txRepo = transaction.getRepository(TxData.class, "rollback"); + + TxData txData1 = new TxData(); + txData1.setId(2L); + txData1.setName("John"); + + TxData txData2 = new TxData(); + txData2.setId(1L); + txData2.setName("Jane Doe"); + txRepo.update(txData2); + txRepo.insert(txData1); + + // just to create UniqueConstraintViolation for rollback + repository.insert(txData1); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 1); + assertEquals(txRepo.find(where("name").eq("Jane Doe")).size(), 1); + assertNotEquals(repository.find(where("name").eq("Jane Doe")).size(), 1); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(repository.find(where("name").eq("Jane")).size(), 1); + assertNotEquals(repository.find(where("name").eq("Jane Doe")).size(), 1); + } + } + } + + @Test + public void testCommitRemove() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + txRepo.remove(where("name").eq("John")); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 0); + assertEquals(repository.find(where("name").eq("John")).size(), 1); + + transaction.commit(); + + assertEquals(repository.find(where("name").eq("John")).size(), 0); + } + } + } + + @Test + public void testRollbackRemove() { + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + TxData txData1 = new TxData(1L, "John"); + repository.insert(txData1); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + txRepo.remove(where("name").eq("John")); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 0); + assertEquals(repository.find(where("name").eq("John")).size(), 1); + + TxData txData2 = new TxData(2L, "Jane"); + txRepo.insert(txData2); + repository.insert(txData2); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(repository.find(where("name").eq("John")).size(), 1); + assertEquals(repository.find(where("name").eq("Jane")).size(), 1); + } + } + } + + @Test + public void testCommitCreateIndex() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.createIndex(indexOptions(IndexType.FULL_TEXT), "name"); + + assertTrue(txRepo.hasIndex("name")); + assertFalse(repository.hasIndex("name")); + + transaction.commit(); + + assertTrue(repository.hasIndex("name")); + } + } + } + + @Test + public void testRollbackCreateIndex() { + TxData txData1 = new TxData(1L, "John"); + TxData txData2 = new TxData(2L, "Jane"); + + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(txData1); + + try(Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.createIndex(indexOptions(IndexType.FULL_TEXT), "name"); + + assertTrue(txRepo.hasIndex("name")); + assertFalse(repository.hasIndex("name")); + + txRepo.insert(txData2); + repository.insert(txData2); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertFalse(repository.hasIndex("name")); + } + } + } + + @Test + public void testCommitClear() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.clear(); + + assertEquals(0, txRepo.size()); + assertEquals(1, repository.size()); + + transaction.commit(); + + assertEquals(0, repository.size()); + } + } + } + + @Test + public void testRollbackClear() { + TxData txData1 = new TxData(1L, "John"); + TxData txData2 = new TxData(2L, "Jane"); + + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try(Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.clear(); + + assertEquals(0, txRepo.size()); + assertEquals(1, repository.size()); + + txRepo.insert(txData2); + repository.insert(txData2); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(2, repository.size()); + } + } + } + + @Test + public void testCommitDropIndex() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.dropIndex("name"); + + assertFalse(txRepo.hasIndex("name")); + assertTrue(repository.hasIndex("name")); + + transaction.commit(); + + assertFalse(repository.hasIndex("name")); + } + } + } + + @Test + public void testRollbackDropIndex() { + TxData txData1 = new TxData(1L, "John"); + TxData txData2 = new TxData(2L, "Jane"); + + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try(Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.dropIndex("name"); + + assertFalse(txRepo.hasIndex("name")); + assertTrue(repository.hasIndex("name")); + + txRepo.insert(txData2); + repository.insert(txData2); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertTrue(repository.hasIndex("name")); + } + } + } + + @Test + public void testCommitDropAllIndices() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.dropAllIndices(); + + assertFalse(txRepo.hasIndex("name")); + assertTrue(repository.hasIndex("name")); + + transaction.commit(); + + assertFalse(repository.hasIndex("name")); + } + } + } + + @Test + public void testRollbackDropAllIndices() { + TxData txData1 = new TxData(1L, "John"); + TxData txData2 = new TxData(2L, "Jane"); + + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try(Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.dropAllIndices(); + + assertFalse(txRepo.hasIndex("name")); + assertTrue(repository.hasIndex("name")); + + txRepo.insert(txData2); + repository.insert(txData2); + + throw new TransactionException("failed"); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertTrue(repository.hasIndex("name")); + } + } + } + + @Test + public void testCommitDropRepository() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.drop(); + + boolean expectedException = false; + try { + assertEquals(0, txRepo.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + assertEquals(1, repository.size()); + + transaction.commit(); + + expectedException = false; + try { + assertEquals(0, repository.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + } + } + } + + @Test + public void testRollbackDropRepository() { + TxData txData1 = new TxData(1L, "John"); + + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try(Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.drop(); + + boolean expectedException = false; + try { + assertEquals(0, txRepo.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + assertEquals(1, repository.size()); + + throw new TransactionException("failed"); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(1, repository.size()); + } + } + } + + @Test + public void testCommitSetAttribute() { + ObjectRepository repository = db.getRepository(TxData.class); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + Attributes attributes = new Attributes(); + Map hashMap = new HashMap<>(); + hashMap.put("key", "value"); + attributes.setAttributes(hashMap); + txRepo.setAttributes(attributes); + + assertNull(repository.getAttributes()); + + transaction.commit(); + + assertEquals("value", repository.getAttributes().get("key")); + } + } + } + + @Test + public void testRollbackSetAttribute() { + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + Attributes attributes = new Attributes(); + Map map = new HashMap<>(); + map.put("key", "value"); + attributes.setAttributes(map); + txRepo.setAttributes(attributes); + + txRepo.insert(new TxData(1L, "John")); + txRepo.insert(new TxData(2L, "Jane")); + + assertNull(repository.getAttributes()); + + // just to create UniqueConstraintViolation for rollback + repository.insert(new TxData(2L, "Jane")); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 1); + assertNotEquals(repository.find(where("name").eq("John")).size(), 1); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertNull(repository.getAttributes().get("key")); + } + } + } + + @Test + public void testConcurrentInsertAndRemove() { + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex(indexOptions(IndexType.NON_UNIQUE), "name"); + Faker faker = new Faker(); + List> futures = new ArrayList<>(); + + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + final long fi = i; + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + for (long j = 0; j < 10; j++) { + TxData txData = new TxData(j + (fi * 10), faker.name().name()); + txRepo.insert(txData); + } + + txRepo.remove(where("id").eq(2L + (fi * 10))); + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(90, repository.size()); + } + } + + @Test + public void testConcurrentInsert() { + ObjectRepository repository = db.getRepository(TxData.class); + Faker faker = new Faker(); + List> futures = new ArrayList<>(); + + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + final long fi = i; + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + for (long j = 0; j < 10; j++) { + TxData txData = new TxData(j + (fi * 10), faker.name().name()); + txRepo.insert(txData); + } + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(100, repository.size()); + } + } + + @Test + public void testConcurrentUpdate() { + ObjectRepository repository = db.getRepository(TxData.class); + Faker faker = new Faker(); + for (long j = 0; j < 10; j++) { + TxData txData = new TxData(j, faker.name().name()); + repository.insert(txData); + } + + List> futures = new ArrayList<>(); + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + for (int j = 0; j < 10; j++) { + TxData txData = new TxData((long) j, faker.name().name()); + txRepo.update(where("id").eq(j), txData); + } + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(10, repository.size()); + } + } + + @Test + public void testTransactionOnDifferentRepositoriesAndCollections() { + ObjectRepository repo1 = db.getRepository(TxData.class); + ObjectRepository repo2 = db.getRepository(TxData.class, "2"); + ObjectRepository repo3 = db.getRepository(SubEmployee.class); + NitriteCollection col1 = db.getCollection("test1"); + col1.createIndex("id"); + + Faker faker = new Faker(); + + try(Session session = db.createSession()) { + Transaction transaction = session.beginTransaction(); + + ObjectRepository txRepo1 = transaction.getRepository(TxData.class); + ObjectRepository txRepo2 = transaction.getRepository(TxData.class, "2"); + ObjectRepository txRepo3 = transaction.getRepository(SubEmployee.class); + NitriteCollection test1 = transaction.getCollection("test1"); + + for (long i = 0; i < 10; i++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", i); + test1.insert(document); + + TxData txData1 = new TxData(i, faker.name().name()); + txRepo1.insert(txData1); + + TxData txData2 = new TxData(i + 10, faker.name().name()); + txRepo2.insert(txData2); + + SubEmployee employee = new SubEmployee(); + employee.setAddress(faker.address().fullAddress()); + employee.setEmpId(i); + employee.setJoinDate(faker.date().birthday()); + txRepo3.insert(employee); + } + + assertEquals(test1.size(), 10); + assertEquals(txRepo1.size(), 10); + assertEquals(txRepo2.size(), 10); + assertEquals(txRepo3.size(), 10); + + assertEquals(col1.size(), 0); + assertEquals(repo1.size(), 0); + assertEquals(repo2.size(), 0); + assertEquals(repo3.size(), 0); + + transaction.commit(); + + assertEquals(col1.size(), 10); + assertEquals(repo1.size(), 10); + assertEquals(repo2.size(), 10); + assertEquals(repo3.size(), 10); + } + + Transaction transaction = null; + try (Session session = db.createSession()) { + transaction = session.beginTransaction(); + + ObjectRepository txRepo1 = transaction.getRepository(TxData.class); + ObjectRepository txRepo2 = transaction.getRepository(TxData.class, "2"); + ObjectRepository txRepo3 = transaction.getRepository(SubEmployee.class); + NitriteCollection test1 = transaction.getCollection("test1"); + + for (long i = 0; i < 10; i++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", i + 10); + test1.insert(document); + + TxData txData1 = new TxData(i + 10, faker.name().name()); + txRepo1.insert(txData1); + + TxData txData2 = new TxData(i + 20, faker.name().name()); + txRepo2.insert(txData2); + + SubEmployee employee = new SubEmployee(); + employee.setAddress(faker.address().fullAddress()); + employee.setEmpId(i + 10); + employee.setJoinDate(faker.date().birthday()); + txRepo3.insert(employee); + } + + assertEquals(test1.size(), 20); + assertEquals(txRepo1.size(), 20); + assertEquals(txRepo2.size(), 20); + assertEquals(txRepo3.size(), 20); + + assertEquals(col1.size(), 10); + assertEquals(repo1.size(), 10); + assertEquals(repo2.size(), 10); + assertEquals(repo3.size(), 10); + + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", 12L); + col1.insert(document); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + + assertEquals(col1.size(), 11); // last doc added + assertEquals(repo1.size(), 10); + assertEquals(repo2.size(), 10); + assertEquals(repo3.size(), 10); + } + } + + @Test(expected = TransactionException.class) + public void testFailureOnClosedTransaction() { + try(Session session = db.createSession()) { + Transaction transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.insert(new TxData(1L, "John")); + transaction.commit(); + + txRepo.insert(new TxData(2L, "Jane")); + fail(); + } + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/transaction/TxData.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/transaction/TxData.java new file mode 100644 index 000000000..1e5ed7ca6 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/transaction/TxData.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.transaction; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +class TxData implements Mappable { + @Id + private Long id; + private String name; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("id", id) + .put("name", name); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Long.class); + name = document.get("name", String.class); + } +} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/migrate/MigrationTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/migrate/MigrationTest.java deleted file mode 100644 index ef7d4d06d..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/migrate/MigrationTest.java +++ /dev/null @@ -1,570 +0,0 @@ -package org.dizitart.no2.migrate; - -import com.github.javafaker.Faker; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.Retry; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.Constants; -import org.dizitart.no2.exceptions.MigrationException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.migration.Instruction; -import org.dizitart.no2.migration.Migration; -import org.dizitart.no2.migration.TypeConverter; -import org.dizitart.no2.mvstore.MVStoreModule; -import org.dizitart.no2.repository.ObjectRepository; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.UUID; - -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.TestUtil.createDb; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -public class MigrationTest { - private final String dbPath = getRandomTempDbFile(); - private Nitrite db; - private Faker faker; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - db = createDb(dbPath); - faker = new Faker(); - } - - @After - public void cleanUp() throws IOException { - if (!db.isClosed()) { - db.close(); - } - - Files.delete(Paths.get(dbPath)); - } - - @Test - public void testRepositoryMigrate() { - ObjectRepository oldRepo = db.getRepository(OldClass.class, "demo1"); - for (int i = 0; i < 10; i++) { - OldClass old = new OldClass(); - old.setEmpId(String.valueOf(faker.number().randomNumber())); - old.setFirstName(faker.name().firstName()); - old.setLastName(faker.name().lastName()); - old.setUuid(UUID.randomUUID().toString()); - - OldClass.Literature literature = new OldClass.Literature(); - literature.setRatings((float) faker.number().randomDouble(2, 1, 5)); - literature.setText(faker.lorem().paragraph()); - old.setLiterature(literature); - - oldRepo.insert(old); - } - - db.close(); - - Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { - @Override - public void migrate(Instruction instruction) { - instruction.forDatabase() - .addPassword("test-user", "test-password"); - - instruction.forRepository(OldClass.class, "demo1") - .renameRepository("new", null) - .changeDataType("empId", (TypeConverter) Long::parseLong) - .changeIdField("uuid", "empId") - .deleteField("uuid") - .renameField("lastName", "familyName") - .addField("fullName", document -> document.get("firstName", String.class) + " " - + document.get("familyName", String.class)) - .dropIndex("firstName") - .dropIndex("literature.text") - .changeDataType("literature.ratings", (TypeConverter) Math::round); - } - }; - - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compress(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate("test-user", "test-password"); - - ObjectRepository newRepo = db.getRepository(NewClass.class); - assertEquals(newRepo.size(), 10); - assertTrue(db.listCollectionNames().isEmpty()); - assertTrue(db.listKeyedRepository().isEmpty()); - - assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 2); - } - - @Test - public void testCollectionMigrate() { - NitriteCollection collection = db.getCollection("test"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - document.put("bloodGroup", faker.name().bloodGroup()); - document.put("age", faker.number().randomDigit()); - - collection.insert(document); - } - - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.NonUnique)); - collection.createIndex("bloodGroup", IndexOptions.indexOptions(IndexType.NonUnique)); - db.close(); - - Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { - @Override - public void migrate(Instruction instruction) { - instruction.forDatabase() - .addPassword("test-user", "test-password"); - - instruction.forCollection("test") - .rename("testCollectionMigrate") - .deleteField("lastName"); - } - }; - - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate("test-user", "test-password"); - - collection = db.getCollection("testCollectionMigrate"); - assertTrue(collection.hasIndex("firstName")); - assertEquals(collection.size(), 10); - assertEquals(db.listCollectionNames().size(), 1); - assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 2); - db.close(); - - migration = new Migration(2, 3) { - @Override - public void migrate(Instruction instruction) { - instruction.forDatabase() - .changePassword("test-user", "test-password", "password"); - - instruction.forCollection("testCollectionMigrate") - .dropIndex("firstName") - .deleteField("bloodGroup") - .addField("name", document -> faker.name().fullName()) - .addField("address") - .addField("vehicles", 1) - .renameField("age", "ageGroup") - .createIndex("ageGroup", IndexType.NonUnique); - } - }; - - storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(3) - .addMigrations(migration) - .openOrCreate("test-user", "password"); - - collection = db.getCollection("testCollectionMigrate"); - assertEquals(collection.size(), 10); - assertEquals(db.listCollectionNames().size(), 1); - assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 3); - - assertFalse(collection.hasIndex("firstName")); - assertTrue(collection.hasIndex("ageGroup")); - assertEquals(collection.find(where("age").notEq(null)).size(), 0); - } - - @Test(expected = MigrationException.class) - public void testOpenWithoutSchemaVersion() { - NitriteCollection collection = db.getCollection("test"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("test") - .rename("testOpenWithoutSchemaVersion") - .deleteField("lastName"); - } - }; - - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testOpenWithoutSchemaVersion"); - assertEquals(collection.size(), 10); - db.close(); - - storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(); - - collection = db.getCollection("testOpenWithoutSchemaVersion"); - assertEquals(collection.size(), 10); - } - - @Test - public void testDescendingSchema() { - NitriteCollection collection = db.getCollection("test"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("test") - .rename("testDescendingSchema") - .deleteField("lastName"); - } - }; - - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testDescendingSchema"); - assertEquals(collection.size(), 10); - db.close(); - - migration = new Migration(2, Constants.INITIAL_SCHEMA_VERSION) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("testDescendingSchema") - .rename("test"); - } - }; - - storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(1) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - } - - @Test - public void testMigrationWithoutVersion() { - NitriteCollection collection = db.getCollection("test"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("test") - .rename("testMigrationWithoutVersion") - .deleteField("lastName"); - } - }; - - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testMigrationWithoutVersion"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - } - - @Test - public void testWrongSchemaVersionNoMigration() { - NitriteCollection collection = db.getCollection("testWrongSchemaVersionNoMigration"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration = new Migration(1, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("testWrongSchemaVersionNoMigration") - .rename("test") - .deleteField("lastName"); - } - }; - - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testWrongSchemaVersionNoMigration"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - - migration = new Migration(2, 3) { - @Override - public void migrate(Instruction instruction) { - instruction.forCollection("test") - .rename("testWrongSchemaVersionNoMigration"); - } - }; - - storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testWrongSchemaVersionNoMigration"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - } - - @Test - public void testReOpenAfterMigration() { - NitriteCollection collection = db.getCollection("testReOpenAfterMigration"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration = new Migration(1, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("testReOpenAfterMigration") - .rename("test") - .deleteField("lastName"); - } - }; - - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testReOpenAfterMigration"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testReOpenAfterMigration"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .openOrCreate(); - - collection = db.getCollection("testReOpenAfterMigration"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - } - - @Test - public void testMultipleMigrations() { - NitriteCollection collection = db.getCollection("testMultipleMigrations"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration1 = new Migration(1, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("testMultipleMigrations") - .rename("test"); - } - }; - - Migration migration2 = new Migration(2, 3) { - @Override - public void migrate(Instruction instruction) { - instruction.forCollection("test") - .addField("fullName", "Dummy Name"); - } - }; - - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration1, migration2) - .openOrCreate(); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - assertEquals(collection.find(where("fullName").eq("Dummy Name")).size(), 0); - db.close(); - - Migration migration3 = new Migration(3, 4) { - @Override - public void migrate(Instruction instruction) { - instruction.forCollection("test") - .addField("age", 10); - } - }; - - storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .compressHigh(true) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(4) - .addMigrations(migration1, migration2, migration3) - .openOrCreate(); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - assertEquals(collection.find(where("fullName").eq("Dummy Name")).size(), 10); - assertEquals(collection.find(where("age").eq(10)).size(), 10); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/migrate/NewClass.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/migrate/NewClass.java deleted file mode 100644 index a9a83d4b2..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/migrate/NewClass.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.dizitart.no2.migrate; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Entity; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; - -/** - * @author Anindya Chatterjee - */ -@Data -@Entity(value = "new", indices = { - @Index(value = "familyName", type = IndexType.NonUnique), - @Index(value = "fullName", type = IndexType.NonUnique), - @Index(value = "literature.ratings", type = IndexType.NonUnique), -}) -public class NewClass implements Mappable { - @Id - private Long empId; - private String firstName; - private String familyName; - private String fullName; - private Literature literature; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("empId", empId) - .put("firstName", firstName) - .put("familyName", familyName) - .put("fullName", fullName) - .put("literature", literature.write(mapper)); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - empId = document.get("empId", Long.class); - firstName = document.get("firstName", String.class); - familyName = document.get("familyName", String.class); - fullName = document.get("fullName", String.class); - - Document doc = document.get("literature", Document.class); - literature = new Literature(); - literature.read(mapper, doc); - } - - @Data - public static class Literature implements Mappable { - private String text; - private Integer ratings; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("text", text) - .put("ratings", ratings); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - text = document.get("text", String.class); - ratings = document.get("ratings", Integer.class); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/migrate/OldClass.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/migrate/OldClass.java deleted file mode 100644 index 7808f3fb2..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/migrate/OldClass.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.dizitart.no2.migrate; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Entity; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; - -/** - * @author Anindya Chatterjee - */ -@Data -@Entity(value = "old", indices = { - @Index(value = "firstName", type = IndexType.NonUnique), - @Index(value = "lastName", type = IndexType.NonUnique), - @Index(value = "literature.text", type = IndexType.Fulltext), - @Index(value = "literature.ratings", type = IndexType.NonUnique), -}) -public class OldClass implements Mappable { - @Id - private String uuid; - private String empId; - private String firstName; - private String lastName; - private Literature literature; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("empId", empId) - .put("uuid", uuid) - .put("firstName", firstName) - .put("lastName", lastName) - .put("literature", literature.write(mapper)); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - empId = document.get("empId", String.class); - uuid = document.get("uuid", String.class); - firstName = document.get("firstName", String.class); - lastName = document.get("lastName", String.class); - - Document doc = document.get("literature", Document.class); - literature = new Literature(); - literature.read(mapper, doc); - } - - @Data - public static class Literature implements Mappable { - private String text; - private Float ratings; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("text", text) - .put("ratings", ratings); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - text = document.get("text", String.class); - ratings = document.get("ratings", Float.class); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/MVStoreConfigTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/MVStoreConfigTest.java new file mode 100644 index 000000000..b38fafab8 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/MVStoreConfigTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.mvstore; + +import org.dizitart.no2.store.events.StoreEventListener; +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; + +public class MVStoreConfigTest { + @Test + public void testConstructor() { + MVStoreConfig actualMvStoreConfig = new MVStoreConfig(); + assertFalse(actualMvStoreConfig.isReadOnly()); + assertTrue(actualMvStoreConfig.eventListeners().isEmpty()); + } + + @Test + public void testAddStoreEventListener() { + MVStoreConfig mvStoreConfig = new MVStoreConfig(); + mvStoreConfig.addStoreEventListener(mock(StoreEventListener.class)); + assertEquals(1, mvStoreConfig.eventListeners().size()); + } +} + diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/MVStoreModuleBuilderTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/MVStoreModuleBuilderTest.java new file mode 100644 index 000000000..0f4d3087d --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/MVStoreModuleBuilderTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.mvstore; + +import org.dizitart.no2.store.events.StoreEventListener; +import org.junit.Test; + +import java.nio.file.Paths; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; + +public class MVStoreModuleBuilderTest { + @Test + public void testConstructor() { + MVStoreModuleBuilder actualMvStoreModuleBuilder = new MVStoreModuleBuilder(); + MVStoreModuleBuilder actualFilePathResult = actualMvStoreModuleBuilder.filePath("Path"); + assertTrue(actualMvStoreModuleBuilder.autoCommit()); + assertFalse(actualMvStoreModuleBuilder.recoveryMode()); + assertFalse(actualMvStoreModuleBuilder.readOnly()); + assertEquals(Short.SIZE, actualMvStoreModuleBuilder.pageSplitSize()); + assertNull(actualMvStoreModuleBuilder.fileStore()); + assertEquals("Path", actualMvStoreModuleBuilder.filePath()); + assertTrue(actualMvStoreModuleBuilder.eventListeners().isEmpty()); + assertNull(actualMvStoreModuleBuilder.encryptionKey()); + assertFalse(actualMvStoreModuleBuilder.compressHigh()); + assertEquals(1024, actualMvStoreModuleBuilder.autoCommitBufferSize()); + assertEquals(Short.SIZE, actualMvStoreModuleBuilder.cacheSize()); + assertFalse(actualMvStoreModuleBuilder.compress()); + assertEquals(Short.SIZE, actualMvStoreModuleBuilder.cacheConcurrency()); + MVStoreConfig dbConfigResult = actualMvStoreModuleBuilder.dbConfig(); + assertNull(dbConfigResult.filePath()); + assertTrue(dbConfigResult.eventListeners().isEmpty()); + assertNull(dbConfigResult.encryptionKey()); + assertFalse(dbConfigResult.compressHigh()); + assertFalse(dbConfigResult.compress()); + assertEquals(0, dbConfigResult.cacheSize()); + assertEquals(0, dbConfigResult.cacheConcurrency()); + assertFalse(dbConfigResult.autoCompact()); + assertEquals(0, dbConfigResult.autoCommitBufferSize()); + assertFalse(dbConfigResult.autoCommit()); + assertEquals(0, dbConfigResult.pageSplitSize()); + assertFalse(dbConfigResult.recoveryMode()); + assertNull(dbConfigResult.fileStore()); + assertFalse(dbConfigResult.isReadOnly()); + assertSame(actualMvStoreModuleBuilder, actualFilePathResult); + } + + @Test + public void testConstructor2() { + MVStoreModuleBuilder actualMvStoreModuleBuilder = new MVStoreModuleBuilder(); + assertTrue(actualMvStoreModuleBuilder.autoCommit()); + assertFalse(actualMvStoreModuleBuilder.recoveryMode()); + assertEquals(Short.SIZE, actualMvStoreModuleBuilder.pageSplitSize()); + assertTrue(actualMvStoreModuleBuilder.eventListeners().isEmpty()); + assertEquals(1024, actualMvStoreModuleBuilder.autoCommitBufferSize()); + assertEquals(Short.SIZE, actualMvStoreModuleBuilder.cacheSize()); + assertEquals(Short.SIZE, actualMvStoreModuleBuilder.cacheConcurrency()); + MVStoreConfig dbConfigResult = actualMvStoreModuleBuilder.dbConfig(); + assertTrue(dbConfigResult.eventListeners().isEmpty()); + assertFalse(dbConfigResult.isReadOnly()); + } + + @Test + public void testFilePath() { + MVStoreModuleBuilder withConfigResult = MVStoreModule.withConfig(); + MVStoreModuleBuilder actualFilePathResult = withConfigResult + .filePath(Paths.get(System.getProperty("java.io.tmpdir"), "test.txt").toFile()); + assertSame(withConfigResult, actualFilePathResult); + assertEquals("/tmp/test.txt", actualFilePathResult.filePath()); + } + + @Test + public void testAddStoreEventListener() { + MVStoreModuleBuilder withConfigResult = MVStoreModule.withConfig(); + assertSame(withConfigResult, withConfigResult.addStoreEventListener(mock(StoreEventListener.class))); + } +} + diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/MVStoreModuleTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/MVStoreModuleTest.java new file mode 100644 index 000000000..13a55b031 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/MVStoreModuleTest.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.mvstore; + +import org.junit.Assert; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class MVStoreModuleTest { + @Test + public void testPlugins() { + Assert.assertEquals(1, (new MVStoreModule("Path")).plugins().size()); + } + + @Test + public void testWithConfig() { + MVStoreModuleBuilder actualWithConfigResult = MVStoreModule.withConfig(); + assertTrue(actualWithConfigResult.autoCommit()); + assertFalse(actualWithConfigResult.recoveryMode()); + assertEquals(Short.SIZE, actualWithConfigResult.pageSplitSize()); + assertTrue(actualWithConfigResult.eventListeners().isEmpty()); + assertEquals(1024, actualWithConfigResult.autoCommitBufferSize()); + assertEquals(Short.SIZE, actualWithConfigResult.cacheSize()); + assertEquals(Short.SIZE, actualWithConfigResult.cacheConcurrency()); + MVStoreConfig dbConfigResult = actualWithConfigResult.dbConfig(); + assertTrue(dbConfigResult.eventListeners().isEmpty()); + assertFalse(dbConfigResult.isReadOnly()); + } + + @Test + public void testGetStore() { + assertTrue((new MVStoreModule("Path")).getStore() instanceof NitriteMVStore); + } +} + diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/MVStoreUtilsTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/MVStoreUtilsTest.java new file mode 100644 index 000000000..af170ebd4 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/MVStoreUtilsTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.mvstore; + +import org.dizitart.no2.store.events.StoreEventListener; +import org.h2.mvstore.MVStore; +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; + +public class MVStoreUtilsTest { + @Test + public void testOpenOrCreate() { + MVStore actualOpenOrCreateResult = MVStoreUtils.openOrCreate(new MVStoreConfig()); + assertFalse(actualOpenOrCreateResult.isReadOnly()); + assertEquals(0L, actualOpenOrCreateResult.getVersionsToKeep()); + assertEquals(0.0, actualOpenOrCreateResult.getUpdateFailureRatio(), 0.0); + assertEquals(0, actualOpenOrCreateResult.getUnsavedMemory()); + assertEquals(0, actualOpenOrCreateResult.getStoreVersion()); + assertTrue(actualOpenOrCreateResult.getStoreHeader().isEmpty()); + assertTrue(actualOpenOrCreateResult.getReuseSpace()); + assertEquals(0, actualOpenOrCreateResult.getRetentionTime()); + assertEquals(48, actualOpenOrCreateResult.getPageSplitSize()); + assertEquals(2, actualOpenOrCreateResult.getMetaMap().size()); + assertEquals(Long.MAX_VALUE, actualOpenOrCreateResult.getMaxPageSize()); + assertEquals(1, actualOpenOrCreateResult.getMapNames().size()); + assertEquals(48, actualOpenOrCreateResult.getKeysPerPage()); + assertEquals(100, actualOpenOrCreateResult.getChunksFillRate()); + assertEquals(0, actualOpenOrCreateResult.getAutoCommitMemory()); + } + + @Test + public void testOpenOrCreate2() { + MVStoreConfig mvStoreConfig = new MVStoreConfig(); + mvStoreConfig.addStoreEventListener(mock(StoreEventListener.class)); + MVStore actualOpenOrCreateResult = MVStoreUtils.openOrCreate(mvStoreConfig); + assertFalse(actualOpenOrCreateResult.isReadOnly()); + assertEquals(0L, actualOpenOrCreateResult.getVersionsToKeep()); + assertEquals(0.0, actualOpenOrCreateResult.getUpdateFailureRatio(), 0.0); + assertEquals(0, actualOpenOrCreateResult.getUnsavedMemory()); + assertEquals(0, actualOpenOrCreateResult.getStoreVersion()); + assertTrue(actualOpenOrCreateResult.getStoreHeader().isEmpty()); + assertTrue(actualOpenOrCreateResult.getReuseSpace()); + assertEquals(0, actualOpenOrCreateResult.getRetentionTime()); + assertEquals(48, actualOpenOrCreateResult.getPageSplitSize()); + assertEquals(2, actualOpenOrCreateResult.getMetaMap().size()); + assertEquals(Long.MAX_VALUE, actualOpenOrCreateResult.getMaxPageSize()); + assertEquals(1, actualOpenOrCreateResult.getMapNames().size()); + assertEquals(48, actualOpenOrCreateResult.getKeysPerPage()); + assertEquals(100, actualOpenOrCreateResult.getChunksFillRate()); + assertEquals(0, actualOpenOrCreateResult.getAutoCommitMemory()); + } +} + diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/NitriteMVMapTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/NitriteMVMapTest.java new file mode 100644 index 000000000..3116ee8b5 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/NitriteMVMapTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.mvstore; + +import org.h2.mvstore.MVMap; +import org.junit.Test; + +import java.util.HashSet; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.*; + +public class NitriteMVMapTest { + @Test + public void testValues() { + NitriteMVMap nitriteMVMap = new NitriteMVMap<>( + (MVMap) mock(MVMap.class), null); + assertTrue(nitriteMVMap.values().toList().isEmpty()); + assertFalse(nitriteMVMap.isEmpty()); + } + + @Test + public void testKeys() { + MVMap objectObjectMap = (MVMap) mock(MVMap.class); + when(objectObjectMap.keySet()).thenReturn(new HashSet<>()); + NitriteMVMap nitriteMVMap = new NitriteMVMap<>(objectObjectMap, null); + assertTrue(nitriteMVMap.keys().toList().isEmpty()); + verify(objectObjectMap).keySet(); + assertFalse(nitriteMVMap.isEmpty()); + } + + @Test(expected = NullPointerException.class) + public void testConstructor() { + NitriteMVMap actualNitriteMVMap = new NitriteMVMap<>( + (MVMap) mock(MVMap.class), null); + actualNitriteMVMap.close(); + assertFalse(actualNitriteMVMap.isEmpty()); + } + + @Test + public void testIsEmpty() { + MVMap objectObjectMap = (MVMap) mock(MVMap.class); + when(objectObjectMap.isEmpty()).thenReturn(true); + assertTrue((new NitriteMVMap<>(objectObjectMap, null)).isEmpty()); + verify(objectObjectMap).isEmpty(); + } +} + diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/NitriteMVStoreTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/NitriteMVStoreTest.java new file mode 100644 index 000000000..99968fe49 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/NitriteMVStoreTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.mvstore; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class NitriteMVStoreTest { + @Test + public void testConstructor() { + NitriteMVStore actualNitriteMVStore = new NitriteMVStore(); + assertNull(actualNitriteMVStore.getStoreConfig()); + assertTrue(actualNitriteMVStore.isClosed()); + assertFalse(actualNitriteMVStore.hasUnsavedChanges()); + assertNotNull(actualNitriteMVStore.getStoreVersion()); + } + + @Test + public void testOpenOrCreate() { + NitriteMVStore nitriteMVStore = new NitriteMVStore(); + nitriteMVStore.setStoreConfig(new MVStoreConfig()); + nitriteMVStore.openOrCreate(); + assertFalse(nitriteMVStore.isReadOnly()); + assertFalse(nitriteMVStore.isClosed()); + assertTrue(nitriteMVStore.hasUnsavedChanges()); + } + + @Test + public void testIsClosed() { + assertTrue((new NitriteMVStore()).isClosed()); + } + + @Test + public void testHasUnsavedChanges() { + assertFalse((new NitriteMVStore()).hasUnsavedChanges()); + } + + @Test + public void testGetStoreVersion() { + assertNotNull((new NitriteMVStore()).getStoreVersion()); + } +} + diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/NitriteMapStressTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/NitriteMapStressTest.java deleted file mode 100644 index e7671aa6f..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/NitriteMapStressTest.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2019-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mvstore; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.Retry; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.store.NitriteMap; -import org.dizitart.no2.store.NitriteStore; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.UUID; - -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.TestUtil.createDb; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee. - */ -public class NitriteMapStressTest { - private final String dbPath = getRandomTempDbFile(); - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testWithInsertReadUpdate() { - db = createDb(dbPath); - - NitriteStore nitriteStore = db.getStore(); - NitriteMap nitriteMap = nitriteStore.openMap("testWithInsertReadUpdate", - String.class, Document.class); - - int count = 10000; - for (int i = 0; i < count; i++) { - Document record = Document.createDocument(); - record.put("firstName", UUID.randomUUID().toString()); - record.put("failed", false); - record.put("lastName", UUID.randomUUID().toString()); - record.put("processed", false); - - nitriteMap.put(UUID.randomUUID().toString(), record); - } - - for (Pair entry : nitriteMap.entries()) { - String key = entry.getFirst(); - Document record = entry.getSecond(); - - record.put("processed", true); - - nitriteMap.put(key, record); - } - - db.close(); - } - - @Test - public void testNullKey() { - db = createDb(dbPath); - NitriteStore nitriteStore = db.getStore(); - NitriteMap nitriteMap = nitriteStore.openMap("testNullKey", - String.class, Document.class); - nitriteMap.put(null, Document.createDocument()); - - assertNotNull(nitriteMap.get(null)); - assertEquals(nitriteMap.size(), 1); - - nitriteMap.put(null, Document.createDocument("first", 1)); - assertNotNull(nitriteMap.get(null)); - assertEquals(nitriteMap.size(), 1); - } - - @Test(expected = ValidationException.class) - public void testNullValue() { - db = createDb(dbPath); - NitriteStore nitriteStore = db.getStore(); - NitriteMap nitriteMap = nitriteStore.openMap("testNullValue", - String.class, Document.class); - nitriteMap.put(null, null); - } - - @Test(expected = ValidationException.class) - public void testNullPutIfAbsent() { - db = createDb(dbPath); - NitriteStore nitriteStore = db.getStore(); - NitriteMap nitriteMap = nitriteStore.openMap("testNullPutIfAbsent", - String.class, Document.class); - nitriteMap.putIfAbsent(null, null); - } - - @After - public void tearDown() throws IOException { - if (db != null && !db.isClosed()) { - db.close(); - } - Files.delete(Paths.get(dbPath)); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/NitriteStoreEventTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/NitriteStoreEventTest.java deleted file mode 100644 index 6e66f2ce1..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/NitriteStoreEventTest.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2019-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mvstore; - -import lombok.Data; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.Retry; -import org.dizitart.no2.store.events.EventInfo; -import org.dizitart.no2.store.events.StoreEventListener; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.concurrent.TimeUnit; - -import static org.awaitility.Awaitility.await; -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee - */ -public class NitriteStoreEventTest { - private String dbFile; - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void before() { - dbFile = getRandomTempDbFile(); - } - - @After - public void cleanup() throws IOException { - if (db != null && !db.isClosed()) { - db.close(); - } - - if (Files.exists(Paths.get(dbFile))) { - Files.delete(Paths.get(dbFile)); - } - } - - @Test - public void testStoreEvents() { - TestStoreEventListener listener = new TestStoreEventListener(); - assertFalse(listener.opened); - assertFalse(listener.committed); - assertFalse(listener.closing); - assertFalse(listener.closed); - - MVStoreModule module = MVStoreModule.withConfig() - .filePath(dbFile) - .addStoreEventListener(listener) - .build(); - - db = Nitrite.builder() - .loadModule(module) - .fieldSeparator(".") - .openOrCreate(); - - await().atMost(1, TimeUnit.SECONDS).until(() -> listener.opened); - assertTrue(listener.opened); - assertFalse(listener.committed); - assertFalse(listener.closing); - assertFalse(listener.closed); - - db.commit(); - - await().atMost(1, TimeUnit.SECONDS).until(() -> listener.committed); - assertTrue(listener.opened); - assertTrue(listener.committed); - assertFalse(listener.closing); - assertFalse(listener.closed); - - db.close(); - - await().atMost(1, TimeUnit.SECONDS).until(() -> listener.closed); - assertTrue(listener.opened); - assertTrue(listener.committed); - assertTrue(listener.closing); - assertTrue(listener.closed); - - db.getStore().unsubscribe(listener); - } - - @Data - private static class TestStoreEventListener implements StoreEventListener { - private boolean opened; - private boolean committed; - private boolean closing; - private boolean closed; - - @Override - public void onEvent(EventInfo eventInfo) { - switch (eventInfo.getEvent()) { - case Opened: - opened = true; - break; - case Commit: - committed = true; - break; - case Closing: - closing = true; - break; - case Closed: - closed = true; - break; - } - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/RecoveryTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/RecoveryTest.java new file mode 100644 index 000000000..26c919907 --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/RecoveryTest.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.mvstore; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; + +public class RecoveryTest { + @Test + public void testRecover() { + assertFalse(Recovery.recover("foo.txt")); + assertFalse(Recovery.recover("File not found: ")); + } +} + diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/ReverseIteratorTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/ReverseIteratorTest.java new file mode 100644 index 000000000..551091b4b --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/ReverseIteratorTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.mvstore; + +import org.dizitart.no2.common.tuples.Pair; +import org.h2.mvstore.MVMap; +import org.junit.Test; + +import java.util.NoSuchElementException; + +import static org.mockito.Mockito.*; + +public class ReverseIteratorTest { + + @Test(expected = NoSuchElementException.class) + public void testConstructor() { + MVMap objectObjectMap = (MVMap) mock(MVMap.class); + when(objectObjectMap.getRoot()).thenThrow(new NoSuchElementException("foo")); + new ReverseIterator<>(objectObjectMap); + verify(objectObjectMap).getRoot(); + } + + @Test + public void testHasNext() { + ReverseIterator reverseIterator = (ReverseIterator) mock(ReverseIterator.class); + when(reverseIterator.hasNext()).thenReturn(true); + reverseIterator.hasNext(); + verify(reverseIterator).hasNext(); + } + + @Test + public void testNext() { + ReverseIterator reverseIterator = (ReverseIterator) mock(ReverseIterator.class); + when(reverseIterator.next()).thenReturn(new Pair<>()); + reverseIterator.next(); + verify(reverseIterator).next(); + } +} + diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/compat/v3/MVMapBuilderTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/compat/v3/MVMapBuilderTest.java new file mode 100644 index 000000000..9488930dc --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/compat/v3/MVMapBuilderTest.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.mvstore.compat.v3; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class MVMapBuilderTest { + @Test + public void testConstructor() { + MVMapBuilder actualMvMapBuilder = new MVMapBuilder<>(); + assertTrue(actualMvMapBuilder.getKeyType() instanceof NitriteDataType); + assertTrue(actualMvMapBuilder.getValueType() instanceof NitriteDataType); + } +} + diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/compat/v3/NitriteDataTypeTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/compat/v3/NitriteDataTypeTest.java new file mode 100644 index 000000000..35b31ccff --- /dev/null +++ b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/mvstore/compat/v3/NitriteDataTypeTest.java @@ -0,0 +1,754 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.mvstore.compat.v3; + +import org.h2.mvstore.WriteBuffer; +import org.junit.Test; + +import java.io.UnsupportedEncodingException; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.UUID; + +import static org.junit.Assert.*; + +public class NitriteDataTypeTest { + @Test + public void testAutoDetectDataTypeGetType() { + assertTrue((new NitriteDataType.BigDecimalType(new NitriteDataType())) + .getType("42") instanceof NitriteDataType.StringType); + assertEquals(4, + (new NitriteDataType.BigDecimalType(new NitriteDataType())).getType(0).typeId); + } + + @Test + public void testBigDecimalTypeConstructor() { + NitriteDataType nitriteDataType = new NitriteDataType(); + NitriteDataType.BigDecimalType actualBigDecimalType = new NitriteDataType.BigDecimalType(nitriteDataType); + assertEquals(9, actualBigDecimalType.typeId); + assertSame(actualBigDecimalType.base, nitriteDataType); + } + + @Test + public void testBigIntegerTypeConstructor() { + NitriteDataType nitriteDataType = new NitriteDataType(); + NitriteDataType.BigIntegerType actualBigIntegerType = new NitriteDataType.BigIntegerType(nitriteDataType); + assertEquals(6, actualBigIntegerType.typeId); + assertSame(actualBigIntegerType.base, nitriteDataType); + } + + @Test + public void testBooleanTypeConstructor() { + NitriteDataType nitriteDataType = new NitriteDataType(); + NitriteDataType.BooleanType actualBooleanType = new NitriteDataType.BooleanType(nitriteDataType); + assertEquals(1, actualBooleanType.typeId); + assertSame(actualBooleanType.base, nitriteDataType); + } + + @Test + public void testByteTypeConstructor() { + NitriteDataType nitriteDataType = new NitriteDataType(); + NitriteDataType.ByteType actualByteType = new NitriteDataType.ByteType(nitriteDataType); + assertEquals(2, actualByteType.typeId); + assertSame(actualByteType.base, nitriteDataType); + } + + @Test + public void testCharacterTypeConstructor() { + NitriteDataType nitriteDataType = new NitriteDataType(); + NitriteDataType.CharacterType actualCharacterType = new NitriteDataType.CharacterType(nitriteDataType); + assertEquals(10, actualCharacterType.typeId); + assertSame(actualCharacterType.base, nitriteDataType); + } + + @Test + public void testDateTypeConstructor() { + NitriteDataType nitriteDataType = new NitriteDataType(); + NitriteDataType.DateType actualDateType = new NitriteDataType.DateType(nitriteDataType); + assertEquals(13, actualDateType.typeId); + assertSame(actualDateType.base, nitriteDataType); + } + + @Test + public void testDoubleTypeConstructor() { + NitriteDataType nitriteDataType = new NitriteDataType(); + NitriteDataType.DoubleType actualDoubleType = new NitriteDataType.DoubleType(nitriteDataType); + assertEquals(8, actualDoubleType.typeId); + assertSame(actualDoubleType.base, nitriteDataType); + } + + @Test + public void testFloatTypeConstructor() { + NitriteDataType nitriteDataType = new NitriteDataType(); + NitriteDataType.FloatType actualFloatType = new NitriteDataType.FloatType(nitriteDataType); + assertEquals(7, actualFloatType.typeId); + assertSame(actualFloatType.base, nitriteDataType); + } + + @Test + public void testIntegerTypeConstructor() { + NitriteDataType nitriteDataType = new NitriteDataType(); + NitriteDataType.IntegerType actualIntegerType = new NitriteDataType.IntegerType(nitriteDataType); + assertEquals(4, actualIntegerType.typeId); + assertSame(actualIntegerType.base, nitriteDataType); + } + + @Test + public void testIsBigInteger() { + assertFalse(NitriteDataType.isBigInteger("Obj")); + assertFalse(NitriteDataType.isBigInteger(null)); + } + + @Test + public void testIsBigDecimal() { + assertFalse(NitriteDataType.isBigDecimal("Obj")); + assertFalse(NitriteDataType.isBigDecimal(null)); + } + + @Test + public void testIsDate() { + assertFalse(NitriteDataType.isDate("Obj")); + assertFalse(NitriteDataType.isDate(null)); + } + + @Test + public void testIsArray() { + assertFalse(NitriteDataType.isArray("Obj")); + assertFalse(NitriteDataType.isArray(null)); + } + + @Test + public void testGetCommonClassId() { + assertEquals(8, NitriteDataType.getCommonClassId(Object.class).intValue()); + assertNull(NitriteDataType.getCommonClassId(null)); + } + + @Test + public void testLongTypeConstructor() { + NitriteDataType nitriteDataType = new NitriteDataType(); + NitriteDataType.LongType actualLongType = new NitriteDataType.LongType(nitriteDataType); + assertEquals(5, actualLongType.typeId); + assertSame(actualLongType.base, nitriteDataType); + } + + @Test + public void testNullTypeConstructor() { + NitriteDataType nitriteDataType = new NitriteDataType(); + NitriteDataType.NullType actualNullType = new NitriteDataType.NullType(nitriteDataType); + assertEquals(0, actualNullType.typeId); + assertSame(actualNullType.base, nitriteDataType); + } + + @Test + public void testObjectArrayTypeConstructor() { + assertEquals(14, (new NitriteDataType.ObjectArrayType(new NitriteDataType())).typeId); + } + + @Test + public void testSerialize() { + byte[] actualSerializeResult = NitriteDataType.serialize("Obj"); + assertEquals(10, actualSerializeResult.length); + assertEquals((byte) 0, actualSerializeResult[2]); + assertEquals((byte) 5, actualSerializeResult[3]); + assertEquals('t', actualSerializeResult[4]); + assertEquals((byte) 0, actualSerializeResult[5]); + assertEquals((byte) 3, actualSerializeResult[6]); + assertEquals('O', actualSerializeResult[7]); + assertEquals('b', actualSerializeResult[8]); + assertEquals('j', actualSerializeResult[9]); + } + + @Test + public void testCompareNotNull() throws UnsupportedEncodingException { + byte[] data1 = "AAAAAAAA".getBytes("UTF-8"); + assertEquals(0, NitriteDataType.compareNotNull(data1, "AAAAAAAA".getBytes("UTF-8"))); + } + + @Test + public void testCompareNotNull2() throws UnsupportedEncodingException { + assertEquals(-1, + NitriteDataType.compareNotNull(new byte[]{0, 'A', 'A', 'A', 'A', 'A', 'A', 'A'}, "AAAAAAAA".getBytes("UTF-8"))); + } + + @Test + public void testCompareNotNull3() throws UnsupportedEncodingException { + byte[] data1 = "￿AAAAAAA".getBytes("UTF-8"); + assertEquals(1, NitriteDataType.compareNotNull(data1, "AAAAAAAA".getBytes("UTF-8"))); + } + + @Test + public void testAutoDetectDataTypeCompare() { + assertEquals(-1, (new NitriteDataType.BigDecimalType(new NitriteDataType())).compare("A Obj", "B Obj")); + assertEquals(-1, (new NitriteDataType.BigDecimalType(new NitriteDataType())).compare(0, "B Obj")); + } + + @Test + public void testBigDecimalTypeCompare() { + assertEquals(-1, (new NitriteDataType.BigDecimalType(new NitriteDataType())).compare("A Obj", "B Obj")); + assertEquals(-1, (new NitriteDataType.BigDecimalType(new NitriteDataType())).compare(0, "B Obj")); + } + + @Test + public void testBigIntegerTypeCompare() { + assertEquals(-1, (new NitriteDataType.BigIntegerType(new NitriteDataType())).compare("A Obj", "B Obj")); + assertEquals(-1, (new NitriteDataType.BigIntegerType(new NitriteDataType())).compare(0, "B Obj")); + } + + @Test + public void testBooleanTypeCompare() { + assertEquals(-1, (new NitriteDataType.BooleanType(new NitriteDataType())).compare("A Obj", "B Obj")); + assertEquals(-1, (new NitriteDataType.BooleanType(new NitriteDataType())).compare(true, "B Obj")); + assertEquals(0, (new NitriteDataType.BooleanType(new NitriteDataType())).compare(true, true)); + } + + @Test + public void testByteTypeCompare() { + assertEquals(-1, (new NitriteDataType.ByteType(new NitriteDataType())).compare("A Obj", "B Obj")); + assertEquals(-1, (new NitriteDataType.ByteType(new NitriteDataType())).compare((byte) 'A', "B Obj")); + assertEquals(0, (new NitriteDataType.ByteType(new NitriteDataType())).compare((byte) 'A', (byte) 'A')); + } + + @Test + public void testCharacterTypeCompare() { + assertEquals(-1, (new NitriteDataType.CharacterType(new NitriteDataType())).compare("A Obj", "B Obj")); + assertEquals(-1, (new NitriteDataType.CharacterType(new NitriteDataType())).compare('\u0000', "B Obj")); + assertEquals(0, (new NitriteDataType.CharacterType(new NitriteDataType())).compare('\u0000', '\u0000')); + } + + @Test + public void testCompare() { + assertEquals(0, (new NitriteDataType()).compare("42", "42")); + assertEquals(-1, (new NitriteDataType()).compare(0, "42")); + assertEquals(1, (new NitriteDataType()).compare("42", 0)); + assertEquals(0, (new NitriteDataType()).compare(0, 0)); + } + + @Test + public void testDateTypeCompare() { + assertEquals(-1, (new NitriteDataType.DateType(new NitriteDataType())).compare("A Obj", "B Obj")); + assertEquals(-1, (new NitriteDataType.DateType(new NitriteDataType())).compare(0, "B Obj")); + } + + @Test + public void testDoubleTypeCompare() { + assertEquals(-1, (new NitriteDataType.DoubleType(new NitriteDataType())).compare("A Obj", "B Obj")); + assertEquals(-1, (new NitriteDataType.DoubleType(new NitriteDataType())).compare(0, "B Obj")); + assertEquals(-1, (new NitriteDataType.DoubleType(new NitriteDataType())).compare(10.0, "B Obj")); + assertEquals(0, (new NitriteDataType.DoubleType(new NitriteDataType())).compare(10.0, 10.0)); + } + + @Test + public void testFloatTypeCompare() { + assertEquals(-1, (new NitriteDataType.FloatType(new NitriteDataType())).compare("A Obj", "B Obj")); + assertEquals(-1, (new NitriteDataType.FloatType(new NitriteDataType())).compare(0, "B Obj")); + assertEquals(-1, (new NitriteDataType.FloatType(new NitriteDataType())).compare(10.0f, "B Obj")); + assertEquals(0, (new NitriteDataType.FloatType(new NitriteDataType())).compare(10.0f, 10.0f)); + } + + @Test + public void testIntegerTypeCompare() { + assertEquals(-1, (new NitriteDataType.IntegerType(new NitriteDataType())).compare("A Obj", "B Obj")); + assertEquals(-1, (new NitriteDataType.IntegerType(new NitriteDataType())).compare(0, "B Obj")); + assertEquals(0, (new NitriteDataType.IntegerType(new NitriteDataType())).compare(0, 0)); + } + + @Test + public void testLongTypeCompare() { + assertEquals(-1, (new NitriteDataType.LongType(new NitriteDataType())).compare("A Obj", "B Obj")); + assertEquals(-1, (new NitriteDataType.LongType(new NitriteDataType())).compare(0L, "B Obj")); + assertEquals(0, (new NitriteDataType.LongType(new NitriteDataType())).compare(0L, 0L)); + } + + @Test + public void testNullTypeCompare() { + assertEquals(-1, (new NitriteDataType.NullType(new NitriteDataType())).compare("A Obj", "B Obj")); + assertEquals(-1, (new NitriteDataType.NullType(new NitriteDataType())).compare(0, "B Obj")); + assertEquals(-1, (new NitriteDataType.NullType(new NitriteDataType())).compare(null, "B Obj")); + assertEquals(1, (new NitriteDataType.NullType(new NitriteDataType())).compare("A Obj", null)); + assertEquals(0, (new NitriteDataType.NullType(new NitriteDataType())).compare(null, null)); + } + + @Test + public void testObjectArrayTypeCompare() { + assertEquals(-1, (new NitriteDataType.ObjectArrayType(new NitriteDataType())).compare("A Obj", "B Obj")); + assertEquals(-1, (new NitriteDataType.ObjectArrayType(new NitriteDataType())).compare(0, "B Obj")); + } + + @Test + public void testSerializedObjectTypeCompare() { + assertEquals(-1, (new NitriteDataType.SerializedObjectType(new NitriteDataType())).compare("A Obj", "B Obj")); + assertEquals(-1, (new NitriteDataType.SerializedObjectType(new NitriteDataType())).compare(0, "B Obj")); + assertEquals(0, (new NitriteDataType.SerializedObjectType(new NitriteDataType())).compare(0, 0)); + } + + @Test + public void testShortTypeCompare() { + assertEquals(-1, (new NitriteDataType.ShortType(new NitriteDataType())).compare("A Obj", "B Obj")); + assertEquals(-1, (new NitriteDataType.ShortType(new NitriteDataType())).compare((short) 0, "B Obj")); + assertEquals(0, (new NitriteDataType.ShortType(new NitriteDataType())).compare((short) 0, (short) 0)); + } + + @Test + public void testStringTypeCompare() { + assertEquals(-1, (new NitriteDataType.StringType(new NitriteDataType())).compare("A Obj", "B Obj")); + assertEquals(-1, (new NitriteDataType.StringType(new NitriteDataType())).compare(0, "B Obj")); + assertEquals(1, (new NitriteDataType.StringType(new NitriteDataType())).compare("A Obj", 0)); + assertEquals(-1, (new NitriteDataType.StringType(new NitriteDataType())).compare(4, "B Obj")); + assertEquals(0, (new NitriteDataType.StringType(new NitriteDataType())).compare(0, 0)); + } + + @Test + public void testUUIDTypeCompare() { + assertEquals(-1, (new NitriteDataType.UUIDType(new NitriteDataType())).compare("A Obj", "B Obj")); + assertEquals(-1, (new NitriteDataType.UUIDType(new NitriteDataType())).compare(0, "B Obj")); + } + + @Test + public void testUUIDTypeCompare2() { + NitriteDataType.UUIDType uuidType = new NitriteDataType.UUIDType(new NitriteDataType()); + assertEquals(1, uuidType.compare(UUID.randomUUID(), "B Obj")); + } + + @Test + public void testAutoDetectDataTypeGetMemory() { + assertEquals(28, (new NitriteDataType.BigDecimalType(new NitriteDataType())).getMemory("42")); + assertEquals(24, (new NitriteDataType.BigDecimalType(new NitriteDataType())).getMemory(0)); + } + + @Test + public void testBigDecimalTypeGetMemory() { + assertEquals(30, (new NitriteDataType.BigDecimalType(new NitriteDataType())).getMemory("Obj")); + assertEquals(24, (new NitriteDataType.BigDecimalType(new NitriteDataType())).getMemory(0)); + } + + @Test + public void testBigDecimalTypeGetMemory2() { + NitriteDataType nitriteDataType = new NitriteDataType(); + nitriteDataType.switchType(1); + assertEquals(30, (new NitriteDataType.BigDecimalType(nitriteDataType)).getMemory("Obj")); + } + + @Test + public void testBigIntegerTypeGetMemory() { + assertEquals(30, (new NitriteDataType.BigIntegerType(new NitriteDataType())).getMemory("Obj")); + assertEquals(24, (new NitriteDataType.BigIntegerType(new NitriteDataType())).getMemory(0)); + } + + @Test + public void testBigIntegerTypeGetMemory2() { + NitriteDataType nitriteDataType = new NitriteDataType(); + nitriteDataType.switchType(1); + assertEquals(30, (new NitriteDataType.BigIntegerType(nitriteDataType)).getMemory("Obj")); + } + + @Test + public void testBooleanTypeGetMemory() { + assertEquals(30, (new NitriteDataType.BooleanType(new NitriteDataType())).getMemory("Obj")); + assertEquals(0, (new NitriteDataType.BooleanType(new NitriteDataType())).getMemory(true)); + assertEquals(24, (new NitriteDataType.BooleanType(new NitriteDataType())).getMemory(0)); + } + + @Test + public void testByteTypeGetMemory() { + assertEquals(30, (new NitriteDataType.ByteType(new NitriteDataType())).getMemory("Obj")); + assertEquals(0, (new NitriteDataType.ByteType(new NitriteDataType())).getMemory((byte) 'A')); + assertEquals(24, (new NitriteDataType.ByteType(new NitriteDataType())).getMemory(0)); + } + + @Test + public void testCharacterTypeGetMemory() { + assertEquals(30, (new NitriteDataType.CharacterType(new NitriteDataType())).getMemory("Obj")); + assertEquals(24, (new NitriteDataType.CharacterType(new NitriteDataType())).getMemory('\u0000')); + assertEquals(24, (new NitriteDataType.CharacterType(new NitriteDataType())).getMemory(0)); + } + + @Test + public void testDateTypeGetMemory() { + assertEquals(30, (new NitriteDataType.DateType(new NitriteDataType())).getMemory("Obj")); + assertEquals(24, (new NitriteDataType.DateType(new NitriteDataType())).getMemory(0)); + } + + @Test + public void testDateTypeGetMemory2() { + NitriteDataType nitriteDataType = new NitriteDataType(); + nitriteDataType.switchType(1); + assertEquals(30, (new NitriteDataType.DateType(nitriteDataType)).getMemory("Obj")); + } + + @Test + public void testDoubleTypeGetMemory() { + assertEquals(30, (new NitriteDataType.DoubleType(new NitriteDataType())).getMemory("Obj")); + assertEquals(24, (new NitriteDataType.DoubleType(new NitriteDataType())).getMemory(0)); + assertEquals(30, (new NitriteDataType.DoubleType(new NitriteDataType())).getMemory(10.0)); + } + + @Test + public void testFloatTypeGetMemory() { + assertEquals(30, (new NitriteDataType.FloatType(new NitriteDataType())).getMemory("Obj")); + assertEquals(24, (new NitriteDataType.FloatType(new NitriteDataType())).getMemory(0)); + assertEquals(24, (new NitriteDataType.FloatType(new NitriteDataType())).getMemory(10.0f)); + } + + @Test + public void testGetMemory() { + assertEquals(30, (new NitriteDataType()).getMemory("Obj")); + assertEquals(24, (new NitriteDataType()).getMemory(0)); + } + + @Test + public void testGetMemory2() { + NitriteDataType nitriteDataType = new NitriteDataType(); + nitriteDataType.switchType(1); + assertEquals(30, nitriteDataType.getMemory("Obj")); + } + + @Test + public void testIntegerTypeGetMemory() { + assertEquals(30, (new NitriteDataType.IntegerType(new NitriteDataType())).getMemory("Obj")); + assertEquals(24, (new NitriteDataType.IntegerType(new NitriteDataType())).getMemory(0)); + } + + @Test + public void testIntegerTypeGetMemory2() { + NitriteDataType nitriteDataType = new NitriteDataType(); + nitriteDataType.switchType(1); + assertEquals(30, (new NitriteDataType.IntegerType(nitriteDataType)).getMemory("Obj")); + } + + @Test + public void testLongTypeGetMemory() { + assertEquals(30, (new NitriteDataType.LongType(new NitriteDataType())).getMemory("Obj")); + assertEquals(30, (new NitriteDataType.LongType(new NitriteDataType())).getMemory(0L)); + assertEquals(24, (new NitriteDataType.LongType(new NitriteDataType())).getMemory(0)); + } + + @Test + public void testNullTypeGetMemory() { + assertEquals(30, (new NitriteDataType.NullType(new NitriteDataType())).getMemory("Obj")); + assertEquals(24, (new NitriteDataType.NullType(new NitriteDataType())).getMemory(0)); + assertEquals(0, (new NitriteDataType.NullType(new NitriteDataType())).getMemory(null)); + } + + @Test + public void testObjectArrayTypeGetMemory() { + assertEquals(30, (new NitriteDataType.ObjectArrayType(new NitriteDataType())).getMemory("Obj")); + assertEquals(24, (new NitriteDataType.ObjectArrayType(new NitriteDataType())).getMemory(0)); + } + + @Test + public void testObjectArrayTypeGetMemory2() { + NitriteDataType nitriteDataType = new NitriteDataType(); + nitriteDataType.switchType(1); + assertEquals(30, (new NitriteDataType.ObjectArrayType(nitriteDataType)).getMemory("Obj")); + } + + @Test + public void testSerializedObjectTypeGetMemory() { + assertEquals(30, (new NitriteDataType.SerializedObjectType(new NitriteDataType())).getMemory("Obj")); + assertEquals(24, (new NitriteDataType.SerializedObjectType(new NitriteDataType())).getMemory(0)); + } + + @Test + public void testSerializedObjectTypeGetMemory2() { + NitriteDataType.SerializedObjectType serializedObjectType = new NitriteDataType.SerializedObjectType( + new NitriteDataType()); + serializedObjectType.write(new WriteBuffer(), 19088743); + assertEquals(30, serializedObjectType.getMemory("Obj")); + } + + @Test + public void testShortTypeGetMemory() { + assertEquals(30, (new NitriteDataType.ShortType(new NitriteDataType())).getMemory("Obj")); + assertEquals(24, (new NitriteDataType.ShortType(new NitriteDataType())).getMemory((short) 0)); + assertEquals(24, (new NitriteDataType.ShortType(new NitriteDataType())).getMemory(0)); + } + + @Test + public void testStringTypeGetMemory() { + assertEquals(30, (new NitriteDataType.StringType(new NitriteDataType())).getMemory("Obj")); + assertEquals(24, (new NitriteDataType.StringType(new NitriteDataType())).getMemory(0)); + assertEquals(24, (new NitriteDataType.StringType(new NitriteDataType())).getMemory(4)); + } + + @Test + public void testStringTypeGetMemory2() { + NitriteDataType nitriteDataType = new NitriteDataType(); + nitriteDataType.switchType(1); + assertEquals(24, (new NitriteDataType.StringType(nitriteDataType)).getMemory(0)); + } + + @Test + public void testUUIDTypeGetMemory() { + assertEquals(30, (new NitriteDataType.UUIDType(new NitriteDataType())).getMemory("Obj")); + assertEquals(24, (new NitriteDataType.UUIDType(new NitriteDataType())).getMemory(0)); + } + + @Test + public void testUUIDTypeGetMemory2() { + NitriteDataType.UUIDType uuidType = new NitriteDataType.UUIDType(new NitriteDataType()); + assertEquals(40, uuidType.getMemory(UUID.randomUUID())); + } + + @Test + public void testBigDecimalTypeRead() { + Object actualReadResult = (new NitriteDataType.BigDecimalType(new NitriteDataType())).read(null, 46); + assertSame(((BigDecimal) actualReadResult).ZERO, actualReadResult); + } + + @Test + public void testBigDecimalTypeRead2() { + Object actualReadResult = (new NitriteDataType.BigDecimalType(new NitriteDataType())).read(null, 47); + assertSame(((BigDecimal) actualReadResult).ONE, actualReadResult); + } + + @Test + public void testBigIntegerTypeRead() { + Object actualReadResult = (new NitriteDataType.BigIntegerType(new NitriteDataType())).read(null, 37); + assertSame(((BigInteger) actualReadResult).ZERO, actualReadResult); + } + + @Test + public void testBigIntegerTypeRead2() { + Object actualReadResult = (new NitriteDataType.BigIntegerType(new NitriteDataType())).read(null, 38); + assertSame(((BigInteger) actualReadResult).ONE, actualReadResult); + } + + @Test + public void testNullTypeRead() { + assertNull((new NitriteDataType.NullType(new NitriteDataType())).read(null, 1)); + } + + @Test + public void testStringTypeRead2() { + assertEquals("", (new NitriteDataType.StringType(new NitriteDataType())).read(null, 88)); + } + + @Test + public void testAutoDetectDataTypeWrite() { + NitriteDataType.BigDecimalType bigDecimalType = new NitriteDataType.BigDecimalType(new NitriteDataType()); + WriteBuffer writeBuffer = new WriteBuffer(); + bigDecimalType.write(writeBuffer, "42"); + assertEquals(1048576, writeBuffer.capacity()); + } + + @Test + public void testAutoDetectDataTypeWrite2() { + NitriteDataType.BigDecimalType bigDecimalType = new NitriteDataType.BigDecimalType(new NitriteDataType()); + WriteBuffer writeBuffer = new WriteBuffer(); + bigDecimalType.write(writeBuffer, new Object[]{"42", "42", "42"}, 3, true); + assertEquals(1048576, writeBuffer.capacity()); + } + + @Test + public void testAutoDetectDataTypeWrite3() { + NitriteDataType.BigDecimalType bigDecimalType = new NitriteDataType.BigDecimalType(null); + assertThrows(ArrayIndexOutOfBoundsException.class, + () -> bigDecimalType.write(new WriteBuffer(), new Object[]{}, 3, true)); + } + + @Test + public void testBigDecimalTypeWrite() { + NitriteDataType.BigDecimalType bigDecimalType = new NitriteDataType.BigDecimalType(new NitriteDataType()); + WriteBuffer writeBuffer = new WriteBuffer(); + bigDecimalType.write(writeBuffer, "Obj"); + assertEquals(1048576, writeBuffer.capacity()); + } + + @Test + public void testBigIntegerTypeWrite() { + NitriteDataType.BigIntegerType bigIntegerType = new NitriteDataType.BigIntegerType(new NitriteDataType()); + WriteBuffer writeBuffer = new WriteBuffer(); + bigIntegerType.write(writeBuffer, "Obj"); + assertEquals(1048576, writeBuffer.capacity()); + } + + @Test + public void testBooleanTypeWrite() { + NitriteDataType.BooleanType booleanType = new NitriteDataType.BooleanType(new NitriteDataType()); + WriteBuffer writeBuffer = new WriteBuffer(); + booleanType.write(writeBuffer, "Obj"); + assertEquals(1048576, writeBuffer.capacity()); + } + + @Test + public void testByteTypeWrite() { + NitriteDataType.ByteType byteType = new NitriteDataType.ByteType(new NitriteDataType()); + WriteBuffer writeBuffer = new WriteBuffer(); + byteType.write(writeBuffer, "Obj"); + assertEquals(1048576, writeBuffer.capacity()); + } + + @Test + public void testCharacterTypeWrite() { + NitriteDataType.CharacterType characterType = new NitriteDataType.CharacterType(new NitriteDataType()); + WriteBuffer writeBuffer = new WriteBuffer(); + characterType.write(writeBuffer, "Obj"); + assertEquals(1048576, writeBuffer.capacity()); + } + + @Test + public void testDateTypeWrite() { + NitriteDataType.DateType dateType = new NitriteDataType.DateType(new NitriteDataType()); + WriteBuffer writeBuffer = new WriteBuffer(); + dateType.write(writeBuffer, "Obj"); + assertEquals(1048576, writeBuffer.capacity()); + } + + @Test + public void testDoubleTypeWrite() { + NitriteDataType.DoubleType doubleType = new NitriteDataType.DoubleType(new NitriteDataType()); + WriteBuffer writeBuffer = new WriteBuffer(); + doubleType.write(writeBuffer, "Obj"); + assertEquals(1048576, writeBuffer.capacity()); + } + + @Test + public void testFloatTypeWrite() { + NitriteDataType.FloatType floatType = new NitriteDataType.FloatType(new NitriteDataType()); + WriteBuffer writeBuffer = new WriteBuffer(); + floatType.write(writeBuffer, "Obj"); + assertEquals(1048576, writeBuffer.capacity()); + } + + @Test + public void testIntegerTypeWrite() { + NitriteDataType.IntegerType integerType = new NitriteDataType.IntegerType(new NitriteDataType()); + WriteBuffer writeBuffer = new WriteBuffer(); + integerType.write(writeBuffer, "Obj"); + assertEquals(1048576, writeBuffer.capacity()); + } + + @Test + public void testLongTypeWrite() { + NitriteDataType.LongType longType = new NitriteDataType.LongType(new NitriteDataType()); + WriteBuffer writeBuffer = new WriteBuffer(); + longType.write(writeBuffer, "Obj"); + assertEquals(1048576, writeBuffer.capacity()); + } + + @Test + public void testNullTypeWrite() { + NitriteDataType.NullType nullType = new NitriteDataType.NullType(new NitriteDataType()); + WriteBuffer writeBuffer = new WriteBuffer(); + nullType.write(writeBuffer, "Obj"); + assertEquals(1048576, writeBuffer.capacity()); + } + + @Test + public void testObjectArrayTypeWrite() { + NitriteDataType.ObjectArrayType objectArrayType = new NitriteDataType.ObjectArrayType(new NitriteDataType()); + WriteBuffer writeBuffer = new WriteBuffer(); + objectArrayType.write(writeBuffer, "Obj"); + assertEquals(1048576, writeBuffer.capacity()); + } + + @Test + public void testSerializedObjectTypeWrite() { + NitriteDataType.SerializedObjectType serializedObjectType = new NitriteDataType.SerializedObjectType( + new NitriteDataType()); + WriteBuffer writeBuffer = new WriteBuffer(); + serializedObjectType.write(writeBuffer, "Obj"); + assertEquals(1048576, writeBuffer.capacity()); + } + + @Test + public void testShortTypeWrite() { + NitriteDataType.ShortType shortType = new NitriteDataType.ShortType(new NitriteDataType()); + WriteBuffer writeBuffer = new WriteBuffer(); + shortType.write(writeBuffer, "Obj"); + assertEquals(1048576, writeBuffer.capacity()); + } + + @Test + public void testStringTypeWrite() { + NitriteDataType.StringType stringType = new NitriteDataType.StringType(new NitriteDataType()); + WriteBuffer writeBuffer = new WriteBuffer(); + stringType.write(writeBuffer, "Obj"); + assertEquals(1048576, writeBuffer.capacity()); + } + + @Test + public void testUUIDTypeWrite() { + NitriteDataType.UUIDType uuidType = new NitriteDataType.UUIDType(new NitriteDataType()); + WriteBuffer writeBuffer = new WriteBuffer(); + uuidType.write(writeBuffer, "Obj"); + assertEquals(1048576, writeBuffer.capacity()); + } + + @Test + public void testSerializedObjectTypeConstructor() { + NitriteDataType nitriteDataType = new NitriteDataType(); + NitriteDataType.SerializedObjectType actualSerializedObjectType = new NitriteDataType.SerializedObjectType( + nitriteDataType); + assertEquals(19, actualSerializedObjectType.typeId); + assertSame(actualSerializedObjectType.base, nitriteDataType); + } + + @Test + public void testShortTypeConstructor() { + NitriteDataType nitriteDataType = new NitriteDataType(); + NitriteDataType.ShortType actualShortType = new NitriteDataType.ShortType(nitriteDataType); + assertEquals(3, actualShortType.typeId); + assertSame(actualShortType.base, nitriteDataType); + } + + @Test + public void testStringTypeConstructor() { + NitriteDataType nitriteDataType = new NitriteDataType(); + NitriteDataType.StringType actualStringType = new NitriteDataType.StringType(nitriteDataType); + assertEquals(11, actualStringType.typeId); + assertSame(actualStringType.base, nitriteDataType); + } + + @Test + public void testUUIDTypeConstructor() { + NitriteDataType nitriteDataType = new NitriteDataType(); + NitriteDataType.UUIDType actualUuidType = new NitriteDataType.UUIDType(nitriteDataType); + assertEquals(12, actualUuidType.typeId); + assertSame(actualUuidType.base, nitriteDataType); + } + + @Test + public void testWrite() { + NitriteDataType nitriteDataType = new NitriteDataType(); + WriteBuffer writeBuffer = new WriteBuffer(); + nitriteDataType.write(writeBuffer, "Obj"); + assertEquals(1048576, writeBuffer.capacity()); + } + + @Test + public void testWrite4() { + NitriteDataType nitriteDataType = new NitriteDataType(); + WriteBuffer writeBuffer = new WriteBuffer(); + nitriteDataType.write(writeBuffer, new Object[]{"42", "42", "42"}, 3, true); + assertEquals(1048576, writeBuffer.capacity()); + } + + @Test + public void testWrite5() { + assertThrows(ArrayIndexOutOfBoundsException.class, + () -> (new NitriteDataType()).write(null, new Object[]{}, 3, true)); + } + + @Test + public void testSwitchType() { + assertTrue((new NitriteDataType()).switchType("Obj") instanceof NitriteDataType.StringType); + assertEquals(4, (new NitriteDataType()).switchType(0).typeId); + } +} + diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/BaseObjectRepositoryTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/BaseObjectRepositoryTest.java deleted file mode 100644 index 6c2150ed2..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/BaseObjectRepositoryTest.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.Retry; -import org.dizitart.no2.mvstore.MVStoreModule; -import org.dizitart.no2.mvstore.MVStoreModuleBuilder; -import org.dizitart.no2.repository.data.*; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Collection; - -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.filters.Filter.ALL; - -@RunWith(value = Parameterized.class) -public abstract class BaseObjectRepositoryTest { - @Parameterized.Parameter - public boolean inMemory = false; - @Parameterized.Parameter(value = 1) - public boolean isProtected = false; - @Parameterized.Parameter(value = 2) - public boolean isCompressed = false; - @Parameterized.Parameter(value = 3) - public boolean isAutoCommit = false; - - protected Nitrite db; - protected ObjectRepository companyRepository; - protected ObjectRepository employeeRepository; - protected ObjectRepository aObjectRepository; - protected ObjectRepository cObjectRepository; - private final String fileName = getRandomTempDbFile(); - - @Rule - public Retry retry = new Retry(3); - - @Parameterized.Parameters(name = "InMemory = {0}, Protected = {1}, " + - "Compressed = {2}, AutoCommit = {3}") - public static Collection data() { - return Arrays.asList(new Object[][]{ - {false, false, false, false}, - {false, false, false, true}, - {false, false, true, false}, - {false, false, true, true}, - {false, true, false, false}, - {false, true, false, true}, - {false, true, true, false}, - {false, true, true, true}, - {true, false, false, false}, - {true, false, false, true}, - {true, false, true, false}, - {true, false, true, true}, - {true, true, false, false}, - {true, true, false, true}, - {true, true, true, false}, - {true, true, true, true}, - }); - } - - @Before - public void setUp() { - openDb(); - - companyRepository = db.getRepository(Company.class); - employeeRepository = db.getRepository(Employee.class); - - aObjectRepository = db.getRepository(ClassA.class); - cObjectRepository = db.getRepository(ClassC.class); - - for (int i = 0; i < 10; i++) { - Company company = DataGenerator.generateCompanyRecord(); - companyRepository.insert(company); - Employee employee = DataGenerator.generateEmployee(); - employee.setEmpId((long) i + 1); - employeeRepository.insert(employee); - - aObjectRepository.insert(ClassA.create(i + 50)); - cObjectRepository.insert(ClassC.create(i + 30)); - } - } - - private void openDb() { - MVStoreModuleBuilder builder = MVStoreModule.withConfig(); - - if (isCompressed) { - builder.compress(true); - } - - if (!isAutoCommit) { - builder.autoCommit(false); - } - - if (!inMemory) { - builder.filePath(fileName); - } - - MVStoreModule storeModule = builder.build(); - NitriteBuilder nitriteBuilder = Nitrite.builder() - .fieldSeparator(".") - .loadModule(storeModule); - - if (isProtected) { - db = nitriteBuilder.openOrCreate("test-user", "test-password"); - } else { - db = nitriteBuilder.openOrCreate(); - } - } - - @After - public void clear() throws IOException { - if (companyRepository != null && !companyRepository.isDropped()) { - companyRepository.remove(ALL); - } - - if (employeeRepository != null && !employeeRepository.isDropped()) { - employeeRepository.remove(ALL); - } - - if (aObjectRepository != null && !aObjectRepository.isDropped()) { - aObjectRepository.remove(ALL); - } - - if (cObjectRepository != null && !cObjectRepository.isDropped()) { - cObjectRepository.remove(ALL); - } - - if (db != null && !db.isClosed()) { - db.commit(); - db.close(); - } - - if (!inMemory) { - Files.delete(Paths.get(fileName)); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/CustomFieldSeparatorTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/CustomFieldSeparatorTest.java deleted file mode 100644 index 8cc25f0d3..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/CustomFieldSeparatorTest.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteConfig; -import org.dizitart.no2.Retry; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.mvstore.MVStoreModule; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; -import org.dizitart.no2.repository.data.Company; -import org.dizitart.no2.repository.data.Note; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.Serializable; -import java.util.Date; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee - */ -public class CustomFieldSeparatorTest { - private Nitrite db; - private ObjectRepository repository; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - MVStoreModule module = MVStoreModule.withConfig() - .compress(true) - .build(); - - db = Nitrite.builder() - .loadModule(module) - .fieldSeparator(":") - .openOrCreate(); - - repository = db.getRepository(EmployeeForCustomSeparator.class); - } - - @After - public void reset() { - (new NitriteConfig()).fieldSeparator("."); - if (db != null && !db.isClosed()) { - db.close(); - } - } - - @Test - public void testFieldSeparator() { - assertEquals(NitriteConfig.getFieldSeparator(), ":"); - } - - @Test - public void testFindByEmbeddedField() { - EmployeeForCustomSeparator employee = new EmployeeForCustomSeparator(); - employee.setCompany(new Company()); - employee.setEmployeeNote(new Note()); - - employee.setEmpId(123L); - employee.setJoinDate(new Date()); - employee.setBlob(new byte[0]); - employee.setAddress("Dummy address"); - - employee.getCompany().setCompanyId(987L); - employee.getCompany().setCompanyName("Dummy Company"); - employee.getCompany().setDateCreated(new Date()); - - employee.getEmployeeNote().setNoteId(567L); - employee.getEmployeeNote().setText("Dummy Note"); - - repository.insert(employee); - - assertEquals(repository.find(where("employeeNote.text").eq("Dummy Note")).size(), 0); - assertEquals(repository.find(where("employeeNote:text").text("Dummy Note")).size(), 1); - - assertEquals(repository.find(where("company.companyName").eq("Dummy Company")).size(), 0); - assertEquals(repository.find(where("company:companyName").eq("Dummy Company")).size(), 1); - } - - @ToString - @EqualsAndHashCode - @Indices({ - @Index(value = "joinDate", type = IndexType.NonUnique), - @Index(value = "address", type = IndexType.Fulltext), - @Index(value = "employeeNote:text", type = IndexType.Fulltext) - }) - public static class EmployeeForCustomSeparator implements Serializable, Mappable { - @Id - @Getter - @Setter - private Long empId; - - @Getter - @Setter - private Date joinDate; - - @Getter - @Setter - private String address; - - @Getter - @Setter - private Company company; - - @Getter - @Setter - private byte[] blob; - - @Getter - @Setter - private Note employeeNote; - - EmployeeForCustomSeparator() { - } - - public EmployeeForCustomSeparator(EmployeeForCustomSeparator copy) { - empId = copy.empId; - joinDate = copy.joinDate; - address = copy.address; - company = copy.company; - blob = copy.blob; - employeeNote = copy.employeeNote; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument().put("empId", empId) - .put("joinDate", joinDate) - .put("address", address) - .put("blob", blob) - .put("company", company.write(mapper)) - .put("employeeNote", employeeNote.write(mapper)); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - empId = document.get("empId", Long.class); - joinDate = document.get("joinDate", Date.class); - address = document.get("address", String.class); - blob = document.get("blob", byte[].class); - employeeNote = new Note(); - Document doc = document.get("employeeNote", Document.class); - employeeNote.read(mapper, doc); - company = new Company(); - doc = document.get("company", Document.class); - company.read(mapper, doc); - } - } - -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/InternalClass.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/InternalClass.java deleted file mode 100644 index b351ac40a..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/InternalClass.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@Data -class InternalClass implements Mappable { - @Id - private long id; - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("id", id) - .put("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Long.class); - name = document.get("name", String.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/NitriteIdAsIdTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/NitriteIdAsIdTest.java deleted file mode 100644 index 777b3a7d3..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/NitriteIdAsIdTest.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.Retry; -import org.dizitart.no2.TestUtil; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.common.util.Iterables; -import org.dizitart.no2.exceptions.InvalidIdException; -import org.dizitart.no2.repository.data.WithNitriteId; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; - -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee - */ -public class NitriteIdAsIdTest { - private final String fileName = getRandomTempDbFile(); - private Nitrite db; - private ObjectRepository repo; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void before() { - db = TestUtil.createDb(fileName); - repo = db.getRepository(WithNitriteId.class); - } - - @After - public void after() throws IOException { - db.close(); - Files.delete(Paths.get(fileName)); - } - - @Test - public void testNitriteIdField() { - WithNitriteId item1 = new WithNitriteId(); - item1.name = "first"; - - WithNitriteId item2 = new WithNitriteId(); - item2.name = "second"; - - repo.insert(item1, item2); - - Cursor cursor = repo.find(); - for (WithNitriteId withNitriteId : cursor) { - System.out.println(withNitriteId.name); - assertNotNull(withNitriteId.idField); - } - - WithNitriteId withNitriteId = cursor.firstOrNull(); - withNitriteId.name = "third"; - - NitriteId id = withNitriteId.idField; - repo.update(withNitriteId); - - WithNitriteId byId = repo.getById(id); - assertEquals(withNitriteId, byId); - assertEquals(repo.size(), 2); - } - - @Test(expected = InvalidIdException.class) - public void setIdDuringInsert() { - WithNitriteId item1 = new WithNitriteId(); - item1.name = "first"; - item1.idField = NitriteId.newId(); - - repo.insert(item1); - } - - @Test - public void changeIdDuringUpdate() { - WithNitriteId item2 = new WithNitriteId(); - item2.name = "second"; - WriteResult result = repo.insert(item2); - NitriteId nitriteId = Iterables.firstOrNull(result); - WithNitriteId byId = repo.getById(nitriteId); - byId.idField = NitriteId.newId(); - - result = repo.update(byId); - assertEquals(result.getAffectedCount(), 0); - assertEquals(repo.size(), 1); - } - -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/ObjectCursorTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/ObjectCursorTest.java deleted file mode 100644 index b5b17c593..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/ObjectCursorTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.repository.data.Employee; -import org.junit.Test; - -import java.util.AbstractCollection; - -/** - * @author Anindya Chatterjee - */ -public class ObjectCursorTest extends BaseObjectRepositoryTest { - - @Test(expected = ValidationException.class) - public void testProjectForInterface() { - Cursor cursor = employeeRepository.find(); - cursor.project(Comparable.class); - } - - @Test(expected = ValidationException.class) - public void testProjectForPrimitive() { - Cursor cursor = employeeRepository.find(); - cursor.project(int.class); - } - - @Test(expected = ValidationException.class) - public void testProjectForArray() { - Cursor cursor = employeeRepository.find(); - cursor.project(String[].class); - } - - @Test(expected = ValidationException.class) - public void testProjectForAbstractClass() { - Cursor cursor = employeeRepository.find(); - cursor.project(AbstractCollection.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/ObjectRepositoryNegativeTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/ObjectRepositoryNegativeTest.java deleted file mode 100644 index ad97d8385..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/ObjectRepositoryNegativeTest.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.Retry; -import org.dizitart.no2.TestUtil; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.*; -import org.dizitart.no2.repository.data.*; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; - -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class ObjectRepositoryNegativeTest { - private final String dbPath = getRandomTempDbFile(); - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - db = TestUtil.createDb(dbPath); - } - - @After - public void close() throws IOException { - db.close(); - db = null; - Files.delete(Paths.get(dbPath)); - } - - @Test(expected = ObjectMappingException.class) - public void testWithCircularReference() { - ObjectRepository repository = db.getRepository(WithCircularReference.class); - - WithCircularReference parent = new WithCircularReference(); - parent.setName("parent"); - WithCircularReference object = new WithCircularReference(); - object.setName("test"); - object.setParent(parent); - // circular reference - parent.setParent(object); - - WriteResult result = repository.insert(object); - for (NitriteId id : result) { - WithCircularReference instance = repository.getById(id); - assertEquals(instance.getName(), object.getName()); - assertEquals(instance.getParent().getName(), object.getParent().getName()); - } - } - - @Test(expected = ObjectMappingException.class) - public void testWithCustomConstructor() { - ObjectRepository repository = db.getRepository(WithCustomConstructor.class); - - WithCustomConstructor object = new WithCustomConstructor("test", 2L); - - WriteResult result = repository.insert(object); - for (NitriteId id : result) { - WithCustomConstructor instance = repository.getById(id); - assertEquals(object.getName(), instance.getName()); - assertEquals(object.getNumber(), instance.getNumber()); - } - } - - @Test(expected = InvalidIdException.class) - public void testWithEmptyStringId() { - ObjectRepository repository = db.getRepository(WithEmptyStringId.class); - WithEmptyStringId object = new WithEmptyStringId(); - object.setName(""); // empty id value - - WriteResult result = repository.insert(object); - for (NitriteId id : result) { - WithEmptyStringId instance = repository.getById(id); - assertEquals(instance, object); - } - } - - @Test(expected = InvalidIdException.class) - public void testWithNullId() { - ObjectRepository repository = db.getRepository(WithNullId.class); - WithNullId object = new WithNullId(); - - WriteResult result = repository.insert(object); - for (NitriteId id : result) { - WithNullId instance = repository.getById(id); - assertEquals(instance, object); - } - } - - @Test(expected = ValidationException.class) - public void testWithValueTypeRepository() { - ObjectRepository repository = db.getRepository(String.class); - repository.insert("test"); - } - - @Test(expected = InvalidOperationException.class) - public void testFindResultRemove() { - ObjectRepository repository = db.getRepository(Employee.class); - repository.insert(DataGenerator.generateEmployee()); - RecordStream result = repository.find(); - result.iterator().remove(); - } - - @Test(expected = InvalidOperationException.class) - public void testWithObjectId() { - ObjectRepository repository = db.getRepository(WithObjectId.class); - WithOutId id = new WithOutId(); - id.setName("test"); - id.setNumber(1); - - WithObjectId object = new WithObjectId(); - object.setWithOutId(id); - repository.insert(object); - } - - @Test(expected = NotIdentifiableException.class) - public void testUpdateNoId() { - ObjectRepository repository = db.getRepository(WithOutId.class); - WithOutId object = new WithOutId(); - object.setName("name"); - object.setNumber(1L); - repository.update(object); - } - - @Test(expected = NotIdentifiableException.class) - public void testRemoveNoId() { - ObjectRepository repository = db.getRepository(WithOutId.class); - WithOutId object = new WithOutId(); - object.setName("name"); - object.setNumber(1L); - repository.remove(object); - } - - @Test(expected = ValidationException.class) - public void testProjectionFailedInstantiate() { - ObjectRepository repository = db.getRepository(WithOutId.class); - WithOutId object = new WithOutId(); - object.setName("name"); - object.setNumber(1L); - repository.insert(object); - - RecordStream project = repository.find().project(NitriteId.class); - assertNull(project.toList()); - } - - @Test(expected = ValidationException.class) - public void testNullInsert() { - ObjectRepository repository = db.getRepository(WithOutId.class); - repository.insert(null); - } - - @Test(expected = InvalidIdException.class) - public void testGetByNullId() { - ObjectRepository repository = db.getRepository(WithPublicField.class); - WithPublicField object = new WithPublicField(); - object.name = "test"; - object.number = 2; - - repository.insert(object); - WithPublicField instance = repository.getById(null); - assertEquals(object.name, instance.name); - assertEquals(object.number, instance.number); - } - - @Test - public void testExternalNitriteId() { - ObjectRepository repository = db.getRepository(WithNitriteId.class); - WithNitriteId obj = new WithNitriteId(); - NitriteId id = NitriteId.createId("1"); - obj.setIdField(id); - obj.setName("testExternalNitriteId"); - WriteResult result = repository.update(obj, true); - - obj = new WithNitriteId(); - id = result.iterator().next(); - obj.setIdField(id); - obj.setName("testExternalNitriteId"); - result = repository.update(obj, true); - assertNotEquals(id.getIdValue(), result.iterator().next().getIdValue()); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/ObjectRepositoryTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/ObjectRepositoryTest.java deleted file mode 100644 index 83da340e3..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/ObjectRepositoryTest.java +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import com.github.javafaker.Faker; -import lombok.Data; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.Retry; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.MappableMapper; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.mvstore.MVStoreModule; -import org.dizitart.no2.repository.annotations.Entity; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.data.*; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Date; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.awaitility.Awaitility.await; -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.module.NitriteModule.module; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class ObjectRepositoryTest { - private final String dbPath = getRandomTempDbFile(); - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - NitriteMapper mapper = new MappableMapper(); - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(module(mapper)) - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(); - } - - @After - public void close() throws IOException { - db.close(); - db = null; - Files.delete(Paths.get(dbPath)); - } - - @Test - public void testWithClassField() { - ObjectRepository repository = db.getRepository(WithClassField.class); - - WithClassField object = new WithClassField(); - object.setName("test"); - object.setClazz(String.class); - - repository.insert(object); - WithClassField instance = repository.getById("test"); - assertEquals(instance.getName(), object.getName()); - assertEquals(instance.getClazz(), object.getClazz()); - } - - @Test - public void testWithFinalField() { - ObjectRepository repository = db.getRepository(WithFinalField.class); - WithFinalField object = new WithFinalField(); - object.setName("test"); - - repository.insert(object); - for (WithFinalField instance : repository.find()) { - assertEquals(object.getName(), instance.getName()); - assertEquals(object.getNumber(), instance.getNumber()); - } - } - - @Test - public void testWithOutGetterSetter() { - ObjectRepository repository = db.getRepository(WithOutGetterSetter.class); - WithOutGetterSetter object = new WithOutGetterSetter(); - - repository.insert(object); - for (WithOutGetterSetter instance : repository.find()) { - assertEquals(object, instance); - } - } - - @Test - public void testWithOutId() { - ObjectRepository repository = db.getRepository(WithOutId.class); - WithOutId object = new WithOutId(); - object.setName("test"); - object.setNumber(2); - - repository.insert(object); - for (WithOutId instance : repository.find()) { - assertEquals(object.getName(), instance.getName()); - assertEquals(object.getNumber(), instance.getNumber()); - } - } - - @Test - public void testWithPublicField() { - ObjectRepository repository = db.getRepository(WithPublicField.class); - WithPublicField object = new WithPublicField(); - object.name = "test"; - object.number = 2; - - repository.insert(object); - WithPublicField instance = repository.getById("test"); - assertEquals(object.name, instance.name); - assertEquals(object.number, instance.number); - } - - @Test - public void testWithTransientField() { - ObjectRepository repository = db.getRepository(WithTransientField.class); - WithTransientField object = new WithTransientField(); - object.setNumber(2); - object.setName("test"); - - repository.insert(object); - WithTransientField instance = repository.getById(2L); - assertNotEquals(object.getName(), instance.getName()); - assertNull(instance.getName()); - assertEquals(object.getNumber(), instance.getNumber()); - } - - @Test - public void testWriteThousandRecords() { - int count = 5000; - - ObjectRepository repository = db.getRepository(StressRecord.class); - - for (int i = 0; i < count; i++) { - StressRecord record = new StressRecord(); - record.setFirstName(UUID.randomUUID().toString()); - record.setFailed(false); - record.setLastName(UUID.randomUUID().toString()); - record.setProcessed(false); - - repository.insert(record); - } - - Cursor cursor - = repository.find(where("failed").eq(false)); - for (StressRecord record : cursor) { - record.setProcessed(true); - repository.update(where("firstName").eq(record.getFirstName()), record); - } - } - - @Test - public void testWithPackagePrivateClass() { - ObjectRepository repository = db.getRepository(InternalClass.class); - InternalClass internalClass = new InternalClass(); - internalClass.setId(1); - internalClass.setName("name"); - - repository.insert(internalClass); - InternalClass instance = repository.getById((long) 1); - assertEquals(internalClass.getName(), instance.getName()); - assertEquals(internalClass.getId(), instance.getId()); - } - - @Test - public void testWithPrivateConstructor() { - ObjectRepository repository = - db.getRepository(WithPrivateConstructor.class); - - WithPrivateConstructor object = WithPrivateConstructor.create("test", 2L); - repository.insert(object); - for (WithPrivateConstructor instance : repository.find()) { - assertEquals(object, instance); - } - } - - @Test - public void testWithDateAsId() { - ObjectRepository repository = db.getRepository(WithDateId.class); - - WithDateId object1 = new WithDateId(); - object1.setId(new Date(1482773634L)); - object1.setName("first date"); - repository.insert(object1); - - WithDateId object2 = new WithDateId(); - object2.setName("second date"); - object2.setId(new Date(1482773720L)); - repository.insert(object2); - - assertEquals(repository.find(where("id").eq(new Date(1482773634L))) - .firstOrNull(), object1); - assertEquals(repository.find(where("id").eq(new Date(1482773720L))) - .firstOrNull(), object2); - } - - @Test - public void testWithIdInheritance() { - ObjectRepository repository = db.getRepository(ChildClass.class); - assertTrue(repository.hasIndex("id")); - assertTrue(repository.hasIndex("date")); - assertTrue(repository.hasIndex("text")); - - ChildClass childClass = new ChildClass(); - childClass.setName("first"); - childClass.setDate(new Date(100000L)); - childClass.setId(1L); - childClass.setText("I am first class"); - repository.insert(childClass); - - childClass = new ChildClass(); - childClass.setName("seconds"); - childClass.setDate(new Date(100001L)); - childClass.setId(2L); - childClass.setText("I am second class"); - repository.insert(childClass); - - childClass = new ChildClass(); - childClass.setName("third"); - childClass.setDate(new Date(100002L)); - childClass.setId(3L); - childClass.setText("I am third class"); - repository.insert(childClass); - - assertEquals(repository.find(where("text").text("class")).size(), 3); - assertEquals(repository.find(where("text").text("second")).size(), 0); // filtered in stop words - assertEquals(repository.find(where("date").eq(new Date(100000L))).size(), 1); - assertEquals(repository.find(where("id").eq(1L)).size(), 1); - } - - @Test - public void testAttributes() { - ObjectRepository repository = db.getRepository(WithDateId.class); - Attributes attributes = new Attributes(repository.getDocumentCollection().getName()); - repository.setAttributes(attributes); - assertEquals(repository.getAttributes(), attributes); - } - - @Test - public void testKeyedRepository() { - // an object repository of employees who are managers - ObjectRepository managerRepo = db.getRepository(Employee.class, "managers"); - - // an object repository of all employee - ObjectRepository employeeRepo = db.getRepository(Employee.class); - - // and object repository of employees who are developers - ObjectRepository developerRepo = db.getRepository(Employee.class, "developers"); - - Employee manager = new Employee(); - manager.setEmpId(1L); - manager.setAddress("abcd"); - manager.setJoinDate(new Date()); - - Employee developer = new Employee(); - developer.setEmpId(2L); - developer.setAddress("xyz"); - developer.setJoinDate(new Date()); - - managerRepo.insert(manager); - employeeRepo.insert(manager, developer); - developerRepo.insert(developer); - - assertTrue(db.hasRepository(Employee.class)); - assertTrue(db.hasRepository(Employee.class, "managers")); - assertTrue(db.hasRepository(Employee.class, "developers")); - - assertEquals(db.listRepositories().size(), 1); - assertEquals(db.listKeyedRepository().size(), 2); - - assertEquals(employeeRepo.find(where("address").eq("abcd")).size(), 1); - assertEquals(employeeRepo.find(where("address").eq("xyz")).size(), 1); - assertEquals(managerRepo.find(where("address").eq("xyz")).size(), 0); - assertEquals(managerRepo.find(where("address").eq("abcd")).size(), 1); - assertEquals(developerRepo.find(where("address").eq("xyz")).size(), 1); - assertEquals(developerRepo.find(where("address").eq("abcd")).size(), 0); - } - - @Test - public void testEntityRepository() { - ObjectRepository managerRepo = db.getRepository(EmployeeEntity.class, "managers"); - ObjectRepository employeeRepo = db.getRepository(EmployeeEntity.class); - ObjectRepository developerRepo = db.getRepository(EmployeeEntity.class, "developers"); - - managerRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); - employeeRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); - developerRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); - - boolean errored = false; - try { - NitriteCollection collection = db.getCollection("entity.employee"); - } catch (ValidationException e) { - errored = true; - } - assertTrue(errored); - - assertTrue(db.listRepositories().contains("entity.employee")); - assertEquals(db.listKeyedRepository().size(), 2); - assertEquals(db.listCollectionNames().size(), 0); - - assertTrue(managerRepo.hasIndex("firstName")); - assertTrue(managerRepo.hasIndex("lastName")); - assertTrue(employeeRepo.hasIndex("lastName")); - assertTrue(employeeRepo.hasIndex("lastName")); - - managerRepo.drop(); - assertEquals(db.listKeyedRepository().size(), 1); - } - - @Test - public void testIssue217() { - ObjectRepository employeeRepo = db.getRepository(EmployeeEntity.class); - AtomicInteger counter = new AtomicInteger(0); - employeeRepo.subscribe(eventInfo -> counter.incrementAndGet()); - - ObjectRepository employeeRepo2 = db.getRepository(EmployeeEntity.class); - employeeRepo2.insert(new EmployeeEntity()); - await().atMost(5, TimeUnit.SECONDS).until(() -> counter.get() == 1); - } - - @Data - @Entity(value = "entity.employee", indices = { - @Index(value = "firstName", type = IndexType.NonUnique), - @Index(value = "lastName", type = IndexType.NonUnique), - }) - private static class EmployeeEntity implements Mappable { - private static final Faker faker = new Faker(); - - @Id - private Long id; - private String firstName; - private String lastName; - - public EmployeeEntity() { - id = faker.number().randomNumber(); - firstName = faker.name().firstName(); - lastName = faker.name().lastName(); - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("id", id) - .put("firstName", firstName) - .put("lastName", lastName); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Long.class); - firstName = document.get("firstName", String.class); - lastName = document.get("lastName", String.class); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/ProjectionTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/ProjectionTest.java deleted file mode 100644 index 30c7d27e9..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/ProjectionTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.repository.data.SubEmployee; -import org.junit.Test; - -import java.util.Iterator; - -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -public class ProjectionTest extends BaseObjectRepositoryTest { - - @Test - public void testHasMore() { - RecordStream iterable = employeeRepository.find().skipLimit(0, 5) - .project(SubEmployee.class); - assertFalse(iterable.isEmpty()); - } - - @Test - public void testSize() { - RecordStream iterable = employeeRepository.find().skipLimit(0, 5) - .project(SubEmployee.class); - assertEquals(iterable.size(), 5); - } - - @Test - public void testToString() { - RecordStream iterable = employeeRepository.find().skipLimit(0, 5) - .project(SubEmployee.class); - assertNotNull(iterable.toString()); - } - - @Test(expected = InvalidOperationException.class) - public void testRemove() { - RecordStream iterable = employeeRepository.find().skipLimit(0, 5) - .project(SubEmployee.class); - Iterator iterator = iterable.iterator(); - if (iterator.hasNext()) { - iterator.next(); - iterator.remove(); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/RepositoryFactoryTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/RepositoryFactoryTest.java deleted file mode 100644 index e012507f7..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/RepositoryFactoryTest.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.Retry; -import org.dizitart.no2.TestUtil; -import org.dizitart.no2.collection.*; -import org.dizitart.no2.collection.events.CollectionEventListener; -import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.common.concurrent.LockService; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexEntry; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.store.NitriteStore; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.util.Collection; - -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee - */ -public class RepositoryFactoryTest { - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testRepositoryFactory() { - RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); - assertNotNull(factory); - } - - @Test(expected = ValidationException.class) - public void testNullType() { - RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); - db = TestUtil.createDb(); - factory.getRepository(db.getConfig(), null, "dummy"); - } - - @Test - public void testNullCollection() { - RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); - db = TestUtil.createDb(); - factory.getRepository(db.getConfig(), DummyCollection.class, null); - } - - @Test(expected = ValidationException.class) - public void testNullContext() { - RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); - factory.getRepository(null, DummyCollection.class, "dummy"); - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - } - - private static class DummyCollection implements NitriteCollection { - - @Override - public WriteResult update(Filter filter, Document update, UpdateOptions updateOptions) { - return null; - } - - @Override - public WriteResult remove(Filter filter, boolean justOne) { - return null; - } - - @Override - public DocumentCursor find() { - return null; - } - - @Override - public DocumentCursor find(Filter filter) { - return null; - } - - @Override - public Document getById(NitriteId nitriteId) { - return null; - } - - @Override - public String getName() { - return null; - } - - @Override - public void createIndex(String field, IndexOptions indexOptions) { - - } - - @Override - public void rebuildIndex(String field, boolean isAsync) { - - } - - @Override - public Collection listIndices() { - return null; - } - - @Override - public boolean hasIndex(String field) { - return false; - } - - @Override - public boolean isIndexing(String field) { - return false; - } - - @Override - public void dropIndex(String field) { - - } - - @Override - public void dropAllIndices() { - - } - - @Override - public WriteResult insert(Document[] elements) { - return null; - } - - @Override - public WriteResult update(Document element, boolean insertIfAbsent) { - return null; - } - - @Override - public WriteResult remove(Document element) { - return null; - } - - @Override - public void clear() { - - } - - @Override - public void drop() { - - } - - @Override - public boolean isDropped() { - return false; - } - - @Override - public boolean isOpen() { - return false; - } - - @Override - public void close() { - - } - - @Override - public long size() { - return 0; - } - - @Override - public NitriteStore getStore() { - return null; - } - - @Override - public void subscribe(CollectionEventListener listener) { - - } - - @Override - public void unsubscribe(CollectionEventListener listener) { - - } - - @Override - public Attributes getAttributes() { - return null; - } - - @Override - public void setAttributes(Attributes attributes) { - - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/RepositoryJoinTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/RepositoryJoinTest.java deleted file mode 100644 index da2c0c8c9..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/RepositoryJoinTest.java +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import lombok.Data; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.Retry; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.Lookup; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.mvstore.MVStoreModule; -import org.dizitart.no2.mvstore.MVStoreModuleBuilder; -import org.dizitart.no2.repository.annotations.Id; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.*; - -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -@RunWith(value = Parameterized.class) -public class RepositoryJoinTest { - @Parameterized.Parameter - public boolean inMemory = false; - @Parameterized.Parameter(value = 1) - public boolean isProtected = false; - @Parameterized.Parameter(value = 2) - public boolean isCompressed = false; - @Parameterized.Parameter(value = 3) - public boolean isAutoCommit = false; - - protected Nitrite db; - private final String fileName = getRandomTempDbFile(); - private ObjectRepository personRepository; - private ObjectRepository
addressRepository; - - @Rule - public Retry retry = new Retry(3); - - @Parameterized.Parameters(name = "InMemory = {0}, Protected = {1}, " + - "Compressed = {2}, AutoCommit = {3}") - public static Collection data() { - return Arrays.asList(new Object[][]{ - {false, false, false, false}, - {false, false, false, true}, - {false, false, true, false}, - {false, false, true, true}, - {false, true, false, false}, - {false, true, false, true}, - {false, true, true, false}, - {false, true, true, true}, - {true, false, false, false}, - {true, false, false, true}, - {true, false, true, false}, - {true, false, true, true}, - {true, true, false, false}, - {true, true, false, true}, - {true, true, true, false}, - {true, true, true, true}, - }); - } - - @Before - public void setUp() { - openDb(); - - personRepository = db.getRepository(Person.class); - addressRepository = db.getRepository(Address.class); - - for (int i = 0; i < 10; i++) { - Person person = new Person(); - person.setId(Integer.toString(i)); - person.setName("Person " + i); - personRepository.insert(person); - - Address address = new Address(); - address.setPersonId(Integer.toString(i)); - address.setStreet("Street address " + i); - addressRepository.insert(address); - - if (i == 5) { - Address address2 = new Address(); - address2.setPersonId(Integer.toString(i)); - address2.setStreet("Street address 2nd " + i); - addressRepository.insert(address2); - } - } - } - - private void openDb() { - MVStoreModuleBuilder builder = MVStoreModule.withConfig(); - - if (isCompressed) { - builder.compress(true); - } - - if (!isAutoCommit) { - builder.autoCommit(false); - } - - if (!inMemory) { - builder.filePath(fileName); - } - - MVStoreModule storeModule = builder.build(); - NitriteBuilder nitriteBuilder = Nitrite.builder() - .fieldSeparator(".") - .loadModule(storeModule); - - if (isProtected) { - db = nitriteBuilder.openOrCreate("test-user1", "test-password1"); - } else { - db = nitriteBuilder.openOrCreate(); - } - } - - @After - public void clear() throws IOException { - if (personRepository != null && !personRepository.isDropped()) { - personRepository.remove(ALL); - } - - if (addressRepository != null && !addressRepository.isDropped()) { - addressRepository.remove(ALL); - } - - if (db != null) { - db.commit(); - db.close(); - } - - if (!inMemory) { - Files.delete(Paths.get(fileName)); - } - } - - @Test - public void testJoin() { - Lookup lookup = new Lookup(); - lookup.setLocalField("id"); - lookup.setForeignField("personId"); - lookup.setTargetField("addresses"); - - RecordStream result - = personRepository.find().join(addressRepository.find(), lookup, - PersonDetails.class); - assertEquals(result.size(), 10); - - for (PersonDetails personDetails : result) { - Address[] addresses = personDetails.addresses.toArray(new Address[0]); - if (personDetails.id.equals("5")) { - assertEquals(addresses.length, 2); - } else { - assertEquals(addresses.length, 1); - assertEquals(addresses[0].personId, personDetails.getId()); - } - } - - result = personRepository.find().skipLimit(0, 5).join(addressRepository.find(), lookup, - PersonDetails.class); - - assertEquals(result.size(), 5); - assertFalse(result.isEmpty()); - assertNotNull(result.toString()); - } - - @Test(expected = InvalidOperationException.class) - public void testRemove() { - Lookup lookup = new Lookup(); - lookup.setLocalField("id"); - lookup.setForeignField("personId"); - lookup.setTargetField("addresses"); - - RecordStream result - = personRepository.find().join(addressRepository.find(), lookup, - PersonDetails.class); - assertEquals(result.size(), 10); - - Iterator iterator = result.iterator(); - if (iterator.hasNext()) { - iterator.next(); - iterator.remove(); - } - } - - @Data - public static class Person implements Mappable { - @Id - private NitriteId nitriteId; - private String id; - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("nitriteId", nitriteId) - .put("id", id) - .put("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - nitriteId = document.get("nitriteId", NitriteId.class); - id = document.get("id", String.class); - name = document.get("name", String.class); - } - } - - @Data - public static class Address implements Mappable { - @Id - private NitriteId nitriteId; - private String personId; - private String street; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("nitriteId", nitriteId) - .put("personId", personId) - .put("street", street); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - nitriteId = document.get("nitriteId", NitriteId.class); - personId = document.get("personId", String.class); - street = document.get("street", String.class); - } - } - - @Data - public static class PersonDetails implements Mappable { - @Id - private NitriteId nitriteId; - private String id; - private String name; - private List
addresses; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("nitriteId", nitriteId) - .put("personId", id) - .put("street", name) - .put("addresses", addresses); - } - - @Override - @SuppressWarnings("unchecked") - public void read(NitriteMapper mapper, Document document) { - nitriteId = document.get("nitriteId", NitriteId.class); - id = document.get("id", String.class); - name = document.get("name", String.class); - Set documents = document.get("addresses", Set.class); - this.addresses = new ArrayList<>(); - for (Document doc : documents) { - Address address = new Address(); - address.read(mapper, doc); - addresses.add(address); - } - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/RepositoryModificationTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/RepositoryModificationTest.java deleted file mode 100644 index 7c0813651..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/RepositoryModificationTest.java +++ /dev/null @@ -1,631 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.InvalidIdException; -import org.dizitart.no2.exceptions.UniqueConstraintException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexEntry; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.repository.data.*; -import org.junit.Test; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Collection; -import java.util.Date; -import java.util.Locale; - -import static org.awaitility.Awaitility.await; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.*; - - -/** - * @author Anindya Chatterjee. - */ -public class RepositoryModificationTest extends BaseObjectRepositoryTest { - - @Test - public void testCreateIndex() { - assertTrue(companyRepository.hasIndex("companyName")); - assertFalse(companyRepository.hasIndex("dateCreated")); - - companyRepository.createIndex("dateCreated", IndexOptions.indexOptions(IndexType.NonUnique)); - assertTrue(companyRepository.hasIndex("dateCreated")); - assertFalse(companyRepository.isIndexing("dateCreated")); - } - - @Test - public void testRebuildIndex() { - companyRepository.createIndex("dateCreated", IndexOptions.indexOptions(IndexType.NonUnique)); - assertFalse(companyRepository.isIndexing("dateCreated")); - - companyRepository.rebuildIndex("dateCreated", true); - assertTrue(companyRepository.isIndexing("dateCreated")); - - await().until(() -> !companyRepository.isIndexing("dateCreated")); - } - - @Test - public void testListIndexes() { - Collection indices = companyRepository.listIndices(); - assertEquals(indices.size(), 2); - - companyRepository.createIndex("dateCreated", IndexOptions.indexOptions(IndexType.NonUnique)); - indices = companyRepository.listIndices(); - assertEquals(indices.size(), 3); - } - - @Test - public void testDropIndex() { - testListIndexes(); - companyRepository.dropIndex("dateCreated"); - Collection indices = companyRepository.listIndices(); - assertEquals(indices.size(), 2); - } - - @Test - public void testDropAllIndex() { - testListIndexes(); - companyRepository.dropAllIndices(); - Collection indices = companyRepository.listIndices(); - assertEquals(indices.size(), 0); - } - - @Test - public void testCompanyRecord() { - Cursor cursor = companyRepository.find(); - assertEquals(cursor.size(), 10); - assertFalse(cursor.isEmpty()); - } - - @Test - public void testInsert() { - Company company = DataGenerator.generateCompanyRecord(); - Cursor cursor = companyRepository.find(); - assertEquals(cursor.size(), 10); - - companyRepository.insert(company); - cursor = companyRepository.find(); - assertEquals(cursor.size(), 11); - - Company company1 = DataGenerator.generateCompanyRecord(); - Company company2 = DataGenerator.generateCompanyRecord(); - companyRepository.insert(new Company[]{company1, company2}); - cursor = companyRepository.find(); - assertEquals(cursor.size(), 13); - } - - @Test - public void testUpdateWithFilter() { - employeeRepository.remove(Filter.ALL); - - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("abcd road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(new Date()); - Note empNote = new Note(); - empNote.setNoteId(23L); - empNote.setText("sample text note"); - employee.setEmployeeNote(empNote); - - employeeRepository.insert(employee); - Cursor result = employeeRepository.find(); - assertEquals(result.size(), 1); - for (Employee e : result) { - assertEquals(e.getAddress(), "abcd road"); - } - - Employee updated = new Employee(employee); - updated.setAddress("xyz road"); - WriteResult writeResult = employeeRepository.update(where("empId").eq(12L), updated); - assertEquals(writeResult.getAffectedCount(), 1); - result = employeeRepository.find(); - assertEquals(result.size(), 1); - for (Employee e : result) { - assertEquals(e.getAddress(), "xyz road"); - } - } - - @Test - public void testUpdateWithJustOnceFalse() throws ParseException { - Date joiningDate = new Date(); - prepareUpdateWithOptions(joiningDate); - - SimpleDateFormat simpleDateFormat - = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); - Date newJoiningDate = simpleDateFormat.parse("2012-07-01T16:02:48.440Z"); - - Document updated1 = createDocument(); - updated1.put("joinDate", newJoiningDate); - - WriteResult writeResult - = employeeRepository.update(where("empId").eq(12L), updated1, false); - assertEquals(writeResult.getAffectedCount(), 1); - - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 1); - result = employeeRepository.find(where("joinDate").eq(newJoiningDate)); - assertEquals(result.size(), 1); - - employeeRepository.remove(Filter.ALL); - prepareUpdateWithOptions(joiningDate); - result = employeeRepository.find(); - assertEquals(result.size(), 2); - - Document update = createDocument(); - update.put("joinDate", newJoiningDate); - - writeResult = employeeRepository.update(where("joinDate").eq(joiningDate), update, false); - assertEquals(writeResult.getAffectedCount(), 2); - - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - - result = employeeRepository.find(where("joinDate").eq(newJoiningDate)); - assertEquals(result.size(), 2); - } - - @Test - public void testUpsertTrue() { - Date joiningDate = new Date(); - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("some road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(joiningDate); - Note empNote1 = new Note(); - empNote1.setNoteId(23L); - empNote1.setText("sample text note"); - employee.setEmployeeNote(empNote1); - - WriteResult writeResult - = employeeRepository.update(where("empId").eq(12), employee, true); - assertEquals(writeResult.getAffectedCount(), 1); - - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 1); - } - - @Test - public void testUpsertFalse() { - Date joiningDate = new Date(); - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("some road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(joiningDate); - Note empNote1 = new Note(); - empNote1.setNoteId(23L); - empNote1.setText("sample text note"); - employee.setEmployeeNote(empNote1); - - WriteResult writeResult - = employeeRepository.update(where("empId").eq(12), employee, false); - assertEquals(writeResult.getAffectedCount(), 0); - - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - } - - @Test - public void testDeleteFilterAndWithOutOption() { - Date joiningDate = new Date(); - prepareUpdateWithOptions(joiningDate); - - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 2); - - WriteResult writeResult = employeeRepository.remove(where("joinDate").eq(joiningDate)); - assertEquals(writeResult.getAffectedCount(), 2); - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - } - - @Test - public void testDeleteFilterAndWithOption() { - Date joiningDate = new Date(); - prepareUpdateWithOptions(joiningDate); - - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 2); - - WriteResult writeResult = employeeRepository.remove(where("joinDate").eq(joiningDate), true); - assertEquals(writeResult.getAffectedCount(), 1); - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 1); - } - - @Test - public void testEmployeeRecord() { - Iterable totalResult = employeeRepository.find(); - int occurrence = 0; - for (Employee employee : totalResult) { - if (employee.getEmployeeNote().getText().toLowerCase().contains("class aptent")) { - occurrence++; - } - } - - Cursor cursor = employeeRepository.find(where("employeeNote.text").text("Class aptent")); - assertEquals(cursor.size(), occurrence); - } - - @Test - public void testUpdateWithOptions() { - Employee employee = employeeRepository.find().firstOrNull(); - - Document update = createDocument(); - update.put("address", "new address"); - - WriteResult writeResult - = employeeRepository.update(where("empId").eq(employee.getEmpId()), update, false); - assertEquals(writeResult.getAffectedCount(), 1); - - Employee byId = employeeRepository.getById(employee.getEmpId()); - assertEquals(byId.getAddress(), "new address"); - assertEquals(byId.getEmpId(), employee.getEmpId()); - - update.put("address", "another address"); - employeeRepository.update(where("empId").eq(employee.getEmpId()), update); - - byId = employeeRepository.getById(employee.getEmpId()); - assertEquals(byId.getAddress(), "another address"); - assertEquals(byId.getEmpId(), employee.getEmpId()); - } - - @Test(expected = InvalidIdException.class) - public void testMultiUpdateWithObject() { - employeeRepository.remove(Filter.ALL); - - Date now = new Date(); - Employee employee1 = new Employee(); - employee1.setEmpId(1L); - employee1.setAddress("abcd"); - employee1.setJoinDate(now); - - Employee employee2 = new Employee(); - employee2.setEmpId(2L); - employee2.setAddress("xyz"); - employee2.setJoinDate(now); - employeeRepository.insert(employee1, employee2); - - Employee update = new Employee(); - update.setAddress("new address"); - - WriteResult writeResult - = employeeRepository.update(where("joinDate").eq(now), update, false); - assertEquals(writeResult.getAffectedCount(), 0); - } - - @Test - public void testUpdateNull() { - Employee employee = employeeRepository.find().firstOrNull(); - Employee newEmployee = new Employee(employee); - newEmployee.setJoinDate(null); - - Employee result = employeeRepository.find(where("empId").eq(employee.getEmpId())).firstOrNull(); - assertNotNull(result.getJoinDate()); - - WriteResult writeResult = employeeRepository.update(newEmployee, false); - assertEquals(writeResult.getAffectedCount(), 1); - - result = employeeRepository.find(where("empId").eq(employee.getEmpId())).firstOrNull(); - assertNull(result.getJoinDate()); - - // update with object filter and item and set id different - } - - @Test - public void testUpdateWithChangedId() { - Employee employee = employeeRepository.find().firstOrNull(); - Long oldId = employee.getEmpId(); - long count = employeeRepository.size(); - - Employee newEmployee = new Employee(employee); - newEmployee.setEmpId(50L); - - Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); - assertNotNull(result.getJoinDate()); - - WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); - assertEquals(writeResult.getAffectedCount(), 1); - - assertEquals(count, employeeRepository.size()); - Cursor cursor = employeeRepository.find(where("empId").eq(oldId)); - assertEquals(cursor.size(), 0); - } - - @Test(expected = InvalidIdException.class) - public void testUpdateWithNullId() { - Employee employee = employeeRepository.find().firstOrNull(); - Long oldId = employee.getEmpId(); - - Employee newEmployee = new Employee(employee); - newEmployee.setEmpId(null); - - Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); - assertNotNull(result.getJoinDate()); - - WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); - assertEquals(writeResult.getAffectedCount(), 1); - } - - @Test(expected = UniqueConstraintException.class) - public void testUpdateWithDuplicateId() { - Employee employee = employeeRepository.find().firstOrNull(); - Long oldId = employee.getEmpId(); - long count = employeeRepository.size(); - - Employee newEmployee = new Employee(employee); - newEmployee.setEmpId(5L); - - Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); - assertNotNull(result.getJoinDate()); - - WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); - assertEquals(writeResult.getAffectedCount(), 1); - - assertEquals(count, employeeRepository.size()); - Cursor cursor = employeeRepository.find(where("empId").eq(oldId)); - assertEquals(cursor.size(), 0); - } - - @Test - public void testUpdateWithObject() { - Employee employee = employeeRepository.find().firstOrNull(); - Employee newEmployee = new Employee(employee); - - Long id = employee.getEmpId(); - String address = employee.getAddress(); - newEmployee.setAddress("new address"); - - WriteResult writeResult = employeeRepository.update(newEmployee); - assertEquals(writeResult.getAffectedCount(), 1); - - Employee emp = employeeRepository.find(where("empId").eq(id)).firstOrNull(); - assertNotEquals(address, emp.getAddress()); - assertEquals(employee.getEmpId(), emp.getEmpId()); - assertEquals(employee.getJoinDate(), emp.getJoinDate()); - assertArrayEquals(employee.getBlob(), emp.getBlob()); - } - - @Test - public void testUpsertWithObject() { - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("some road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(new Date()); - Note empNote = new Note(); - empNote.setNoteId(23L); - empNote.setText("sample text note"); - employee.setEmployeeNote(empNote); - - WriteResult writeResult = employeeRepository.update(employee, false); - assertEquals(writeResult.getAffectedCount(), 0); - writeResult = employeeRepository.update(employee, true); - assertEquals(writeResult.getAffectedCount(), 1); - - Employee emp = employeeRepository.find(where("empId").eq(12L)).firstOrNull(); - assertEquals(emp, employee); - } - - @Test - public void testRemoveObject() { - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("some road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(new Date()); - Note empNote = new Note(); - empNote.setNoteId(23L); - empNote.setText("sample text note"); - employee.setEmployeeNote(empNote); - - long size = employeeRepository.size(); - - employeeRepository.insert(employee); - assertEquals(employeeRepository.size(), size + 1); - - employeeRepository.remove(employee); - assertEquals(employeeRepository.size(), size); - - Employee emp = employeeRepository.find(where("empId").eq(12L)).firstOrNull(); - assertNull(emp); - } - - private void prepareUpdateWithOptions(Date joiningDate) { - employeeRepository.remove(Filter.ALL); - - Employee employee1 = new Employee(); - employee1.setCompany(null); - employee1.setAddress("some road"); - employee1.setBlob(new byte[]{1, 2, 125}); - employee1.setEmpId(12L); - employee1.setJoinDate(joiningDate); - Note empNote1 = new Note(); - empNote1.setNoteId(23L); - empNote1.setText("sample text note"); - employee1.setEmployeeNote(empNote1); - - Employee employee2 = new Employee(); - employee2.setCompany(null); - employee2.setAddress("other road"); - employee2.setBlob(new byte[]{10, 12, 25}); - employee2.setEmpId(2L); - employee2.setJoinDate(joiningDate); - Note empNote2 = new Note(); - empNote2.setNoteId(2L); - empNote2.setText("some random note"); - employee2.setEmployeeNote(empNote2); - - employeeRepository.insert(employee1, employee2); - Cursor result = employeeRepository.find(); - assertEquals(result.size(), 2); - for (Employee e : result.project(Employee.class)) { - assertEquals(e.getJoinDate(), joiningDate); - } - } - - @Test - public void testUpdateWithDoc() { - Note note = new Note(); - note.setNoteId(10L); - note.setText("some note text"); - - Document document = createDocument("address", "some address") - .put("employeeNote", note); - - WriteResult result = employeeRepository.update(Filter.ALL, document); - assertEquals(result.getAffectedCount(), 10); - } - - @Test - public void testDeleteIteratorNPE() { - ObjectRepository notes = db.getRepository(Note.class); - Note one = new Note(); - one.setText("Jane"); - one.setNoteId(1L); - Note two = new Note(); - two.setText("Jill"); - two.setNoteId(2L); - - notes.insert(one, two); - - WriteResult writeResult = notes.remove(where("text").eq("Pete")); - for (NitriteId id : writeResult) { - assertNotNull(id); - } - } - - @Test - public void testDelete() { - ObjectRepository repo = db.getRepository(WithNitriteId.class); - WithNitriteId one = new WithNitriteId(); - one.setName("Jane"); - repo.insert(one); - - WithNitriteId note = repo.find().firstOrNull(); - repo.remove(note); - - assertNull(repo.getById(one.idField)); - } - - /* - * Upsert Use Cases - * - * 1. Object does not exists - * a. if upsert true, it will insert - * b. if upsert false, nothing happens - * 2. Object exists - * a. if upsert true, it will update, old id remains same - * b. if upsert false, it will update, old id remains same - * - * */ - - @Test - public void testUpdateObjectNotExistsUpsertTrue() { - ObjectRepository repo = db.getRepository(InternalClass.class); - InternalClass a = new InternalClass(); - a.setId(1); - a.setName("first"); - repo.insert(a); - - a = new InternalClass(); - a.setId(2); - a.setName("second"); - - // it will insert as new object - repo.update(a, true); - assertEquals(repo.size(), 2); - } - - @Test - public void testUpdateObjectNotExistsUpsertFalse() { - ObjectRepository repo = db.getRepository(InternalClass.class); - InternalClass a = new InternalClass(); - a.setId(1); - a.setName("first"); - repo.insert(a); - - a = new InternalClass(); - a.setId(2); - a.setName("second"); - - // no changes will happen to repository - repo.update(a, false); - assertEquals(repo.size(), 1); - assertEquals(repo.find().firstOrNull().getId(), 1); - assertEquals(repo.find().firstOrNull().getName(), "first"); - } - - @Test - public void testUpdateObjectExistsUpsertTrue() { - ObjectRepository repo = db.getRepository(InternalClass.class); - InternalClass a = new InternalClass(); - a.setId(1); - a.setName("first"); - repo.insert(a); - - a = new InternalClass(); - a.setId(1); - a.setName("second"); - - // update existing object, keep id same - repo.update(a, true); - assertEquals(repo.size(), 1); - assertEquals(repo.find().firstOrNull().getId(), 1); - assertEquals(repo.find().firstOrNull().getName(), "second"); - } - - @Test - public void testUpdateObjectExistsUpsertFalse() { - ObjectRepository repo = db.getRepository(InternalClass.class); - InternalClass a = new InternalClass(); - a.setId(1); - a.setName("first"); - repo.insert(a); - - a = new InternalClass(); - a.setId(1); - a.setName("second"); - - // update existing object, keep id same - repo.update(a, false); - assertEquals(repo.size(), 1); - assertEquals(repo.find().firstOrNull().getId(), 1); - assertEquals(repo.find().firstOrNull().getName(), "second"); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/RepositoryOperationsTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/RepositoryOperationsTest.java deleted file mode 100644 index 44a8b5609..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/RepositoryOperationsTest.java +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import lombok.Getter; -import org.dizitart.no2.DbTestOperations; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.Retry; -import org.dizitart.no2.TestUtil; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.exceptions.IndexingException; -import org.dizitart.no2.exceptions.NotIdentifiableException; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.InheritIndices; -import org.dizitart.no2.repository.data.Employee; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.math.BigDecimal; -import java.util.Iterator; -import java.util.Set; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -/** - * @author Anindya Chatterjee - */ -public class RepositoryOperationsTest { - private RepositoryOperations operations; - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - db = TestUtil.createDb(); - } - - @Test - public void testIndexes() { - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(TestObjectWithIndex.class); - operations = new RepositoryOperations(TestObjectWithIndex.class, nitriteMapper, repository.getDocumentCollection()); - Set indexes = operations.extractIndices(TestObjectWithIndex.class); - assertEquals(indexes.size(), 2); - } - - @Test(expected = IndexingException.class) - public void testInvalidIndexNonComparable() { - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(ObjectWithNonComparableIndex.class); - operations = new RepositoryOperations(TestObjectWithIndex.class, nitriteMapper, repository.getDocumentCollection()); - Set indexes = operations.extractIndices(ObjectWithNonComparableIndex.class); - assertEquals(indexes.size(), 2); - } - - @Test(expected = IndexingException.class) - public void testInvalidIndexComparableAndIterable() { - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(ObjectWithIterableIndex.class); - operations = new RepositoryOperations(ObjectWithIterableIndex.class, nitriteMapper, repository.getDocumentCollection()); - operations.extractIndices(ObjectWithIterableIndex.class); - } - - @Test(expected = ValidationException.class) - public void testGetFieldsUpToNullStartClass() { - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(Employee.class); - operations = new RepositoryOperations(Employee.class, nitriteMapper, repository.getDocumentCollection()); - assertEquals(operations.getFieldsUpto(null, null).size(), 0); - } - - @Test(expected = ValidationException.class) - public void testGetFieldNoSuchField() { - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(ClassWithAnnotatedFields.class); - operations = new RepositoryOperations(ClassWithAnnotatedFields.class, nitriteMapper, repository.getDocumentCollection()); - operations.getField(getClass(), "test"); - } - - @Test - public void testGetFieldsUpTo() { - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(Employee.class); - operations = new RepositoryOperations(TestObjectWithIndex.class, nitriteMapper, repository.getDocumentCollection()); - - assertEquals(operations.getFieldsUpto(A.class, B.class).size(), 3); - assertEquals(operations.getFieldsUpto(A.class, Object.class).size(), 5); - assertEquals(operations.getFieldsUpto(A.class, null).size(), 5); - - assertEquals(operations.getFieldsUpto(ClassWithAnnotatedFields.class, - Object.class).size(), 5); - assertEquals(operations.getFieldsUpto(ClassWithAnnotatedFields.class, - null).size(), 5); - assertEquals(operations.getFieldsUpto(ClassWithAnnotatedFields.class, - ClassWithNoAnnotatedFields.class).size(), 3); - } - - @Test(expected = NotIdentifiableException.class) - public void testCreateUniqueFilterInvalidId() { - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(B.class); - operations = new RepositoryOperations(B.class, nitriteMapper, repository.getDocumentCollection()); - - B b = new B(); - operations.createUniqueFilter(b); - } - - @Test(expected = NotIdentifiableException.class) - public void testGetIdFieldMultipleId() { - class Test implements Mappable { - @Id - private String id1; - - @Id - private Long id2; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("id1", id1) - .put("id2", id2); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id1 = document.get("id1", String.class); - id2 = document.get("id2", Long.class); - } - } - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(Test.class); - operations = new RepositoryOperations(Test.class, nitriteMapper, repository.getDocumentCollection()); - - operations.getIdField(Test.class); - } - - @Test(expected = ValidationException.class) - public void testInvalidEmbeddedKey() { - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(ClassWithAnnotatedFields.class); - operations = new RepositoryOperations(ClassWithAnnotatedFields.class, nitriteMapper, repository.getDocumentCollection()); - operations.getField(ClassWithAnnotatedFields.class, ".."); - } - - @Test(expected = ValidationException.class) - public void testInvalidGetField() { - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(ClassWithAnnotatedFields.class); - operations = new RepositoryOperations(ClassWithAnnotatedFields.class, nitriteMapper, repository.getDocumentCollection()); - operations.getField(ClassWithAnnotatedFields.class, "fake.fake"); - } - - @Test(expected = ValidationException.class) - public void testExtractInvalidIndex() { - @Index(value = "fake") - class Test implements Mappable { - private String test; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument().put("test", test); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - test = document.get("test", String.class); - } - } - - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(Test.class); - operations = new RepositoryOperations(Test.class, nitriteMapper, repository.getDocumentCollection()); - - operations.extractIndices(Test.class); - } - - @Test - public void testFindAnnotationFromInterface() { - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(TestInterface.class); - operations = new RepositoryOperations(TestInterface.class, nitriteMapper, repository.getDocumentCollection()); - - Set indices = operations.extractIndices(TestInterface.class); - assertFalse(indices.isEmpty()); - } - - @Index(value = "value") - private interface Interface { - String getValue(); - } - - private static class ClassWithAnnotatedFields extends ClassWithNoAnnotatedFields { - @Deprecated - Long longValue; - private String stringValue; - @Deprecated - private String anotherValue; - - @Deprecated - public ClassWithAnnotatedFields() { - } - - @Override - public Document write(NitriteMapper mapper) { - return super.write(mapper) - .put("stringValue", stringValue) - .put("anotherValue", anotherValue) - .put("longValue", longValue); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - super.read(mapper, document); - stringValue = document.get("stringValue", String.class); - anotherValue = document.get("anotherValue", String.class); - longValue = document.get("longValue", Long.class); - } - } - - private static class ClassWithNoAnnotatedFields implements Mappable { - private String stringValue; - private Integer integer; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument().put("stringValue", stringValue) - .put("integer", integer); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - stringValue = document.get("stringValue", String.class); - integer = document.get("integer", Integer.class); - } - } - - private static class A extends B { - private String a; - private Long b; - private Integer c; - } - - private static class B implements Mappable { - String a; - private Short d; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("a", a) - .put("d", d); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - a = document.get("a", String.class); - d = document.get("d", Short.class); - } - } - - @Index(value = "testClass") - private static class ObjectWithNonComparableIndex implements Mappable { - private DbTestOperations testClass; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument("testClass", testClass); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - testClass = document.get("testClass", DbTestOperations.class); - } - } - - @Index(value = "testClass") - private static class ObjectWithIterableIndex implements Mappable { - private TestClass testClass; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("testClass", testClass.write(mapper)); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - TestClass tc = new TestClass(); - tc.read(mapper, document.get("testClass", Document.class)); - testClass = tc; - } - } - - private static class TestClass implements Comparable, Iterable, Mappable { - @Override - public int compareTo(TestClass o) { - return 0; - } - - @Override - public Iterator iterator() { - return null; - } - - @Override - public Document write(NitriteMapper mapper) { - return createDocument(); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - - } - } - - @InheritIndices - private static class TestInterface implements Interface, Mappable { - @Getter - private String value; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument().put("value", value); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - value = document.get("value", String.class); - } - } - - @Index(value = "longValue") - @Index(value = "decimal") - private class TestObjectWithIndex implements Mappable { - private long longValue; - - private TestObject testObject; - - private BigDecimal decimal; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("longValue", longValue) - .put("testObject", testObject.write(mapper)) - .put("decimal", decimal.toPlainString()); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - longValue = document.get("longValue", Long.class); - testObject = new TestObject(); - testObject.read(mapper, document.get("testObject", Document.class)); - String decimalString = document.get("decimal", String.class); - decimal = new BigDecimal(decimalString); - } - } - - @Index(value = "longValue") - private class TestObject implements Mappable { - private String stringValue; - - private Long longValue; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("stringValue", stringValue) - .put("longValue", longValue); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - stringValue = document.get("stringValue", String.class); - longValue = document.get("longValue", Long.class); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/RepositorySearchTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/RepositorySearchTest.java deleted file mode 100644 index 3f836505a..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/RepositorySearchTest.java +++ /dev/null @@ -1,604 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import lombok.Getter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.exceptions.InvalidIdException; -import org.dizitart.no2.exceptions.NotIdentifiableException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.data.*; -import org.junit.Test; - -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.List; - -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.$; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class RepositorySearchTest extends BaseObjectRepositoryTest { - @Test - public void testFindWithOptions() { - Cursor cursor = employeeRepository.find().skipLimit(0, 1); - assertEquals(cursor.size(), 1); - assertNotNull(cursor.firstOrNull()); - } - - @Test - public void testEmployeeProjection() { - List employeeList = employeeRepository.find().toList(); - List subEmployeeList - = employeeRepository.find().project(SubEmployee.class).toList(); - - assertNotNull(employeeList); - assertNotNull(subEmployeeList); - - assertTrue(employeeList.size() > 0); - assertTrue(subEmployeeList.size() > 0); - - assertEquals(employeeList.size(), subEmployeeList.size()); - - for (int i = 0; i < subEmployeeList.size(); i++) { - Employee employee = employeeList.get(i); - SubEmployee subEmployee = subEmployeeList.get(i); - - assertEquals(employee.getEmpId(), subEmployee.getEmpId()); - assertEquals(employee.getJoinDate(), subEmployee.getJoinDate()); - assertEquals(employee.getAddress(), subEmployee.getAddress()); - } - - Cursor cursor = employeeRepository.find(); - assertNotNull(cursor.firstOrNull()); - assertNotNull(cursor.toString()); - assertEquals(cursor.toList().size(), employeeList.size()); - assertNotNull(cursor.firstOrNull()); - assertEquals(cursor.toList().size(), employeeList.size()); - } - - @Test - public void testEmptyResultProjection() { - employeeRepository.remove(ALL); - assertNull(employeeRepository.find().firstOrNull()); - - assertNull(employeeRepository.find(where("empId").eq(-1)) - .firstOrNull()); - } - - @Test - public void testGetById() { - ObjectRepository empRepo = db.getRepository(Employee.class); - Employee e1 = DataGenerator.generateEmployee(); - Employee e2 = DataGenerator.generateEmployee(); - Employee e3 = DataGenerator.generateEmployee(); - Employee e4 = DataGenerator.generateEmployee(); - - e1.setEmpId(1000000L); - e2.setEmpId(2000000L); - e3.setEmpId(3000000L); - e4.setEmpId(4000000L); - - empRepo.insert(e1, e2, e3, e4); - - Employee byId = empRepo.getById(2000000L); - assertEquals(byId, e2); - } - - @Test(expected = NotIdentifiableException.class) - public void testGetByIdNoId() { - ObjectRepository repository = db.getRepository(Note.class); - Note n1 = DataGenerator.randomNote(); - Note n2 = DataGenerator.randomNote(); - Note n3 = DataGenerator.randomNote(); - - assert n1 != null; - n1.setNoteId(1000000L); - assert n2 != null; - n2.setNoteId(2000000L); - assert n3 != null; - n3.setNoteId(3000000L); - - repository.insert(n1, n2, n3); - - repository.getById(2000000L); - } - - @Test(expected = InvalidIdException.class) - public void testGetByIdNullId() { - ObjectRepository empRepo = db.getRepository(Employee.class); - Employee e1 = DataGenerator.generateEmployee(); - Employee e2 = DataGenerator.generateEmployee(); - Employee e3 = DataGenerator.generateEmployee(); - Employee e4 = DataGenerator.generateEmployee(); - - e1.setEmpId(1000000L); - e2.setEmpId(2000000L); - e3.setEmpId(3000000L); - e4.setEmpId(4000000L); - - empRepo.insert(e1, e2, e3, e4); - - empRepo.getById(null); - } - - @Test(expected = InvalidIdException.class) - public void testGetByIdWrongType() { - ObjectRepository empRepo = db.getRepository(Employee.class); - Employee e1 = DataGenerator.generateEmployee(); - Employee e2 = DataGenerator.generateEmployee(); - Employee e3 = DataGenerator.generateEmployee(); - Employee e4 = DataGenerator.generateEmployee(); - - e1.setEmpId(1000000L); - e2.setEmpId(2000000L); - e3.setEmpId(3000000L); - e4.setEmpId(4000000L); - - empRepo.insert(e1, e2, e3, e4); - - Employee byId = empRepo.getById("employee"); - assertNull(byId); - } - - @Test - public void testEqualFilterById() { - Employee employee = employeeRepository.find().firstOrNull(); - long empId = employee.getEmpId(); - Employee emp = employeeRepository.find(where("empId").eq(empId)) - .project(Employee.class).firstOrNull(); - assertEquals(employee, emp); - } - - @Test - public void testEqualFilter() { - Employee employee = employeeRepository.find() - .firstOrNull(); - - Employee emp = employeeRepository.find(where("joinDate").eq(employee.getJoinDate())) - .project(Employee.class) - .firstOrNull(); - assertEquals(employee, emp); - } - - @Test - public void testStringEqualFilter() { - ObjectRepository repository = db.getRepository(ProductScore.class); - - ProductScore object = new ProductScore(); - object.setProduct("test"); - object.setScore(1); - repository.insert(object); - - object = new ProductScore(); - object.setProduct("test"); - object.setScore(2); - repository.insert(object); - - object = new ProductScore(); - object.setProduct("another-test"); - object.setScore(3); - repository.insert(object); - - assertEquals(repository.find(where("product").eq("test")).size(), 2); - } - - @Test - public void testAndFilter() { - Employee emp = employeeRepository.find().firstOrNull(); - - long id = emp.getEmpId(); - String address = emp.getAddress(); - Date joinDate = emp.getJoinDate(); - - Employee employee = employeeRepository.find( - where("empId").eq(id) - .and( - where("address").regex(address) - .and( - where("joinDate").eq(joinDate)))).firstOrNull(); - - assertEquals(emp, employee); - } - - @Test - public void testOrFilter() { - Employee emp = employeeRepository.find().firstOrNull(); - long id = emp.getEmpId(); - - Employee employee = employeeRepository.find( - where("empId").eq(id) - .or( - where("address").regex("n/a") - .or( - where("joinDate").eq(null)))).firstOrNull(); - - assertEquals(emp, employee); - } - - @Test - public void testNotFilter() { - Employee emp = employeeRepository.find().firstOrNull(); - long id = emp.getEmpId(); - - Employee employee = employeeRepository.find( - where("empId").eq(id).not()).firstOrNull(); - assertNotEquals(emp, employee); - } - - @Test - public void testGreaterFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Ascending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").gt(id)) - .toList(); - - assertFalse(employeeList.contains(emp)); - assertEquals(employeeList.size(), 9); - } - - @Test - public void testGreaterEqualFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Ascending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").gte(id)) - .toList(); - - assertTrue(employeeList.contains(emp)); - assertEquals(employeeList.size(), 10); - } - - @Test - public void testLesserThanFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Descending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").lt(id)) - .toList(); - - assertFalse(employeeList.contains(emp)); - assertEquals(employeeList.size(), 9); - } - - @Test - public void testLesserEqualFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Descending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").lte(id)) - .toList(); - - assertTrue(employeeList.contains(emp)); - assertEquals(employeeList.size(), 10); - } - - @Test - public void testTextFilter() { - Employee emp = employeeRepository.find().firstOrNull(); - String text = emp.getEmployeeNote().getText(); - - List employeeList = employeeRepository.find(where("employeeNote.text").text(text)) - .toList(); - - assertTrue(employeeList.contains(emp)); - } - - @Test - public void testRegexFilter() { - RecordStream employees = employeeRepository.find(); - int count = employees.toList().size(); - - List employeeList = employeeRepository.find(where("employeeNote.text").regex(".*")) - .toList(); - - assertEquals(employeeList.size(), count); - } - - @Test - public void testInFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Descending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").in(id, id - 1, id - 2)) - .toList(); - - assertTrue(employeeList.contains(emp)); - assertEquals(employeeList.size(), 3); - - employeeList = employeeRepository.find(where("empId").in(id - 1, id - 2)).toList(); - assertEquals(employeeList.size(), 2); - } - - @Test - public void testNotInFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Descending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").notIn(id, id - 1, id - 2)) - .toList(); - - assertFalse(employeeList.contains(emp)); - assertEquals(employeeList.size(), 7); - - employeeList = employeeRepository.find(where("empId").notIn(id - 1, id - 2)).toList(); - assertEquals(employeeList.size(), 8); - } - - @Test - public void testElemMatchFilter() { - final ProductScore score1 = new ProductScore("abc", 10); - final ProductScore score2 = new ProductScore("abc", 8); - final ProductScore score3 = new ProductScore("abc", 7); - final ProductScore score4 = new ProductScore("xyz", 5); - final ProductScore score5 = new ProductScore("xyz", 7); - final ProductScore score6 = new ProductScore("xyz", 8); - - ObjectRepository repository = db.getRepository(ElemMatch.class); - ElemMatch e1 = new ElemMatch() {{ - setId(1); - setStrArray(new String[]{"a", "b"}); - setProductScores(new ProductScore[]{score1, score4}); - }}; - ElemMatch e2 = new ElemMatch() {{ - setId(2); - setStrArray(new String[]{"d", "e"}); - setProductScores(new ProductScore[]{score2, score5}); - }}; - ElemMatch e3 = new ElemMatch() {{ - setId(3); - setStrArray(new String[]{"a", "f"}); - setProductScores(new ProductScore[]{score3, score6}); - }}; - - repository.insert(e1, e2, e3); - - List elements = repository.find( - where("productScores").elemMatch( - where("product").eq("xyz") - .and(where("score").gte(8)))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("score").lte(8).not())).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("product").eq("xyz") - .or(where("score").gte(8)))).toList(); - assertEquals(elements.size(), 3); - - elements = repository.find( - where("productScores").elemMatch( - where("product").eq("xyz"))).toList(); - assertEquals(elements.size(), 3); - - elements = repository.find( - where("productScores").elemMatch( - where("score").gte(10))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("score").gt(8))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("score").lt(7))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("score").lte(7))).toList(); - assertEquals(elements.size(), 3); - - elements = repository.find( - where("productScores").elemMatch( - where("score").in(7, 8))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find( - where("productScores").elemMatch( - where("score").notIn(7, 8))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("product").regex("xyz"))).toList(); - assertEquals(elements.size(), 3); - - elements = repository.find(where("strArray").elemMatch($.eq("a"))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find( - where("strArray").elemMatch( - $.eq("a") - .or($.eq("f") - .or($.eq("b"))).not())).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find(where("strArray").elemMatch($.gt("e"))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find(where("strArray").elemMatch($.gte("e"))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find(where("strArray").elemMatch($.lte("b"))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find(where("strArray").elemMatch($.lt("a"))).toList(); - assertEquals(elements.size(), 0); - - elements = repository.find(where("strArray").elemMatch($.in("a", "f"))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find(where("strArray").elemMatch($.regex("a"))).toList(); - assertEquals(elements.size(), 2); - } - - @Test - public void testFilterAll() { - ObjectRepository repository = db.getRepository(ElemMatch.class); - Cursor cursor = repository.find(ALL); - assertNotNull(cursor); - assertEquals(cursor.size(), 0); - - repository.insert(new ElemMatch()); - cursor = repository.find(ALL); - assertNotNull(cursor); - assertEquals(cursor.size(), 1); - } - - @Test - public void testEqualsOnTextIndex() { - PersonEntity p1 = new PersonEntity("jhonny"); - PersonEntity p2 = new PersonEntity("jhonny"); - PersonEntity p3 = new PersonEntity("jhonny"); - - ObjectRepository repository = db.getRepository(PersonEntity.class); - repository.insert(p1); - repository.insert(p2); - repository.insert(p3); - - List sameNamePeople = repository.find(where("name").eq("jhonny")).toList(); - assertEquals(sameNamePeople.size(), 3); - - sameNamePeople = repository.find(where("name").eq("JHONNY")).toList(); - assertEquals(sameNamePeople.size(), 0); - - sameNamePeople = repository.find(where("name").text("jhonny")).toList(); - assertEquals(sameNamePeople.size(), 3); - - sameNamePeople = repository.find(where("name").text("JHONNY")).toList(); - assertEquals(sameNamePeople.size(), 3); - - sameNamePeople = repository.find(where("name").eq("jhon*")).toList(); - assertEquals(sameNamePeople.size(), 0); - - sameNamePeople = repository.find(where("name").text("jhon*")).toList(); - assertEquals(sameNamePeople.size(), 3); - } - - @Test - public void testIssue62() { - PersonEntity p1 = new PersonEntity("abcd"); - p1.setStatus("Married"); - - PersonEntity p2 = new PersonEntity("efgh"); - p2.setStatus("Married"); - - PersonEntity p3 = new PersonEntity("ijkl"); - p3.setStatus("Un-Married"); - - ObjectRepository repository = db.getRepository(PersonEntity.class); - repository.insert(p1); - repository.insert(p2); - repository.insert(p3); - - Filter married = where("status").eq("Married"); - - assertEquals(repository.find(married).size(), 2); - assertEquals(repository.find(married).sort("status", SortOrder.Descending).size(), 2); - - assertEquals(repository.find().sort("status", SortOrder.Descending).firstOrNull().getStatus(), "Un-Married"); - - assertEquals(repository.find().sort("status", SortOrder.Ascending).size(), 3); - assertEquals(repository.find().sort("status", SortOrder.Ascending).firstOrNull().getStatus(), "Married"); - } - - @Test - public void testRepeatableIndexAnnotation() { - ObjectRepository repo = db.getRepository(RepeatableIndexTest.class); - RepeatableIndexTest first = new RepeatableIndexTest(); - first.setAge(12); - first.setFirstName("fName"); - first.setLastName("lName"); - repo.insert(first); - - assertTrue(repo.hasIndex("firstName")); - assertTrue(repo.hasIndex("age")); - assertTrue(repo.hasIndex("lastName")); - - assertEquals(repo.find(where("age").eq(12)).firstOrNull(), first); - } - - @Test - public void testIdSet() { - Cursor employees = employeeRepository.find().sort("empId", SortOrder.Ascending); - assertEquals(employees.size(), 10); - } - - @Test - public void testBetweenFilter() { - @Getter - class TestData implements Mappable { - private Date age; - - public TestData(Date age) { - this.age = age; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("age", age); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - age = document.get("age", Date.class); - } - } - - TestData data1 = new TestData(new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime()); - TestData data2 = new TestData(new GregorianCalendar(2021, Calendar.FEBRUARY, 12).getTime()); - TestData data3 = new TestData(new GregorianCalendar(2022, Calendar.MARCH, 13).getTime()); - TestData data4 = new TestData(new GregorianCalendar(2023, Calendar.APRIL, 14).getTime()); - TestData data5 = new TestData(new GregorianCalendar(2024, Calendar.MAY, 15).getTime()); - TestData data6 = new TestData(new GregorianCalendar(2025, Calendar.JUNE, 16).getTime()); - - ObjectRepository repository = db.getRepository(TestData.class); - repository.insert(data1, data2, data3, data4, data5, data6); - - Cursor cursor = repository.find(where("age").between( - new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), - new GregorianCalendar(2025, Calendar.JUNE, 16).getTime())); - assertEquals(cursor.size(), 6); - - cursor = repository.find(where("age").between( - new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), - new GregorianCalendar(2025, Calendar.JUNE, 16).getTime(), false)); - assertEquals(cursor.size(), 4); - - cursor = repository.find(where("age").between( - new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), - new GregorianCalendar(2025, Calendar.JUNE, 16).getTime(), false, true)); - assertEquals(cursor.size(), 5); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/UnAnnotatedObjectTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/UnAnnotatedObjectTest.java deleted file mode 100644 index 45a55d9b4..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/UnAnnotatedObjectTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - - -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.repository.data.ClassA; -import org.dizitart.no2.repository.data.ClassC; -import org.junit.Test; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -/** - * @author Anindya Chatterjee. - */ -public class UnAnnotatedObjectTest extends BaseObjectRepositoryTest { - - @Test - @SuppressWarnings("unchecked") - public void testFind() { - Cursor cursor = aObjectRepository.find(); - assertEquals(cursor.size(), 10); - assertFalse(cursor.isEmpty()); - - IndexOptions indexOptions = new IndexOptions(); - indexOptions.setIndexType(IndexType.Unique); - aObjectRepository.createIndex("b.number", indexOptions); - - cursor = aObjectRepository.find(where("b.number").eq(160).not()). - sort("b.number", SortOrder.Ascending).skipLimit(0, 10); - - System.out.println("Available - " + !cursor.isEmpty()); - System.out.println("Total Size - " + cursor.size()); - - Iterable findRecord = cursor.project(ClassA.class); - for (ClassA classA : findRecord) { - System.out.println(classA); - } - - cursor = aObjectRepository.find(where("b.number").eq(160).not()). - sort("b.number", SortOrder.Descending).skipLimit(2, 7); - - System.out.println("Available - " + !cursor.isEmpty()); - System.out.println("Total Size - " + cursor.size()); - - findRecord = cursor.project(ClassA.class); - for (ClassA classA : findRecord) { - System.out.println(classA); - } - - cursor = cObjectRepository.find(where("id").gt(900)). - sort("id", SortOrder.Descending).skipLimit(2, 7); - System.out.println("Available - " + !cursor.isEmpty()); - System.out.println("Total Size - " + cursor.size()); - - Iterable findRecordC = cursor.project(ClassC.class); - for (ClassC classC : findRecordC) { - System.out.println(classC); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/UniversalTextTokenizerTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/UniversalTextTokenizerTest.java deleted file mode 100644 index 7dea86ff7..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/UniversalTextTokenizerTest.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.index.NitriteTextIndexer; -import org.dizitart.no2.index.fulltext.Languages; -import org.dizitart.no2.index.fulltext.UniversalTextTokenizer; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.mvstore.MVStoreModule; -import org.dizitart.no2.mvstore.MVStoreModuleBuilder; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; - -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.module.NitriteModule.module; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -/** - * @author Anindya Chatterjee - */ -public class UniversalTextTokenizerTest extends BaseObjectRepositoryTest { - private final String fileName = getRandomTempDbFile(); - private ObjectRepository textRepository; - - @Before - @Override - public void setUp() { - openDb(); - - textRepository = db.getRepository(TextData.class); - - for (int i = 0; i < 10; i++) { - TextData data = new TextData(); - data.id = i; - if (i % 2 == 0) { - data.text = "তারা বলল, “এস আমরা আমাদের জন্যে এক বড় শহর বানাই| আর এমন একটি উঁচু স্তম্ভ বানাই " + - "যা আকাশ স্পর্শ করবে| তাহলে আমরা বিখ্যাত হব এবং এটা আমাদের এক সঙ্গে ধরে রাখবে| সারা পৃথিবীতে " + - "আমরা ছড়িয়ে থাকব না|”"; - } else if (i % 3 == 0) { - data.text = "部汁楽示時葉没式将場参右属。覧観将者雄日語山銀玉襲政著約域費。新意虫跡更味株付安署審完顔団。" + - "困更表転定一史賀面政巣迎文学豊税乗。白間接特時京転閉務講封新内。側流効表害場測投活聞秀職探画労。" + - "福川順式極木注美込行警検直性禁遅。土一詳非物質紙姿漢人内池銀周街躍澹二。平討聞述並時全経詳業映回作朝送恵時。"; - } else if (i % 5 == 0) { - data.text = " أقبل لسفن العالم، في أما, بـ بال أملاً الثالث،. الذود بالرّد الثالث، مع" + - " قام, كردة الضغوط الإمداد أن وصل. ٠٨٠٤ عُقر انتباه يكن قد, أن زهاء وفنلندا بال. لان ما يقوم المعاهدات," + - " بـ بخطوط استعملت عدد. صفحة لفشل ولاتّساع لم قام, في مكثّفة الكونجرس جعل, الثالث، واقتصار دون ان.\n"; - } else { - data.text = "Lorem ipsum dolor sit amet, nobis audire perpetua eu sea. Te semper causae " + - "efficiantur per. Qui affert dolorum at. Mel tale constituto interesset in."; - } - textRepository.insert(data); - } - } - - @After - @Override - public void clear() throws IOException { - if (textRepository != null && !textRepository.isDropped()) { - textRepository.remove(ALL); - } - - if (db != null) { - db.commit(); - db.close(); - } - - if (!inMemory) { - Files.delete(Paths.get(fileName)); - } - } - - private void openDb() { - MVStoreModuleBuilder builder = MVStoreModule.withConfig(); - - if (isCompressed) { - builder.compress(true); - } - - if (!isAutoCommit) { - builder.autoCommit(false); - } - - if (!inMemory) { - builder.filePath(fileName); - } - - MVStoreModule storeModule = builder.build(); - NitriteBuilder nitriteBuilder = Nitrite.builder() - .fieldSeparator(".") - .loadModule(storeModule); - - UniversalTextTokenizer tokenizer; - if (isCompressed) { - tokenizer = new UniversalTextTokenizer(Languages.Bengali, Languages.Chinese, Languages.English); - } else { - tokenizer = new UniversalTextTokenizer(Languages.ALL); - } - nitriteBuilder.loadModule(module(new NitriteTextIndexer(tokenizer))); - - if (isProtected) { - db = nitriteBuilder.openOrCreate("test-user", "test-password"); - } else { - db = nitriteBuilder.openOrCreate(); - } - } - - @Test - public void testUniversalFullTextIndexing() { - Cursor cursor = textRepository.find(where("text").text("Lorem")); - assertEquals(cursor.size(), 2); - for (TextData data : cursor) { - System.out.println("Id for English text -> " + data.id); - if (data.id % 2 == 0 || data.id % 3 == 0 || data.id % 5 == 0) { - fail(); - } - } - - cursor = textRepository.find(where("text").text("শহর")); - assertEquals(cursor.size(), 5); - for (TextData data : cursor) { - System.out.println("Id for Bengali text -> " + data.id); - if (data.id % 2 != 0) { - fail(); - } - } - - cursor = textRepository.find(where("text").text("転閉")); - assertEquals(cursor.size(), 0); - cursor = textRepository.find(where("text").text("*転閉*")); - assertEquals(cursor.size(), 2); - for (TextData data : cursor) { - System.out.println("Id for Chinese text -> " + data.id); - if (data.id % 3 != 0) { - fail(); - } - } - - cursor = textRepository.find(where("text").text("أقبل")); - if (isCompressed) { - assertEquals(cursor.size(), 1); - for (TextData data : cursor) { - System.out.println("Id for Arabic text -> " + data.id); - if (data.id % 5 != 0) { - fail(); - } - } - } else { - // أقبل eliminated as stop word - assertEquals(cursor.size(), 0); - } - } - - @Indices( - @Index(value = "text", type = IndexType.Fulltext) - ) - public static class TextData implements Mappable { - public int id; - public String text; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("id", id) - .put("text", text); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Integer.class); - text = document.get("text", String.class); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ChildClass.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ChildClass.java deleted file mode 100644 index 454880872..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ChildClass.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.repository.annotations.InheritIndices; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@InheritIndices -public class ChildClass extends ParentClass { - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return super.write(mapper).put("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - super.read(mapper, document); - name = document.get("name", String.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ClassA.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ClassA.java deleted file mode 100644 index 4cdce3acc..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ClassA.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.util.UUID; - -@EqualsAndHashCode -@ToString -public class ClassA implements Mappable { - @Getter - @Setter - private ClassB classB; - @Getter - @Setter - private UUID uid; - @Getter - @Setter - private String string; - @Getter - @Setter - private byte[] blob; - - public static ClassA create(int seed) { - ClassB classB = ClassB.create(seed); - ClassA classA = new ClassA(); - classA.classB = classB; - classA.uid = new UUID(seed, seed + 50); - classA.string = Integer.toHexString(seed); - classA.blob = new byte[]{(byte) seed}; - return classA; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("classB", classB != null ? classB.write(mapper) : null) - .put("uid", uid) - .put("string", string) - .put("blob", blob); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - if (document.get("classB") != null) { - classB = new ClassB(); - classB.read(mapper, document.get("classB", Document.class)); - } - uid = document.get("uid", UUID.class); - string = document.get("string", String.class); - blob = document.get("blob", byte[].class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ClassB.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ClassB.java deleted file mode 100644 index 9be7793e8..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ClassB.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -@EqualsAndHashCode -@ToString -class ClassB implements Comparable, Mappable { - @Getter - @Setter - private int number; - @Getter - @Setter - private String text; - - static ClassB create(int seed) { - ClassB classB = new ClassB(); - classB.setNumber(seed + 100); - classB.setText(Integer.toBinaryString(seed)); - return classB; - } - - @Override - public int compareTo(ClassB o) { - return Integer.compare(number, o.number); - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("number", number) - .put("text", text); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - number = document.get("number", Integer.class); - text = document.get("text", String.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ClassC.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ClassC.java deleted file mode 100644 index 4402a7109..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ClassC.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -@EqualsAndHashCode -@ToString -public class ClassC implements Mappable { - @Getter - @Setter - private long id; - @Getter - @Setter - private double digit; - @Getter - @Setter - private ClassA parent; - - public static ClassC create(int seed) { - ClassC classC = new ClassC(); - classC.id = seed * 5000; - classC.digit = seed * 69.65; - classC.parent = ClassA.create(seed); - return classC; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("id", id) - .put("digit", digit) - .put("parent", parent != null ? parent.write(mapper) : null); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Long.class); - digit = document.get("digit", Double.class); - if (document.get("parent") != null) { - parent = new ClassA(); - parent.read(mapper, document.get("parent", Document.class)); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/Company.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/Company.java deleted file mode 100644 index 8171c4bff..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/Company.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; - -import java.io.Serializable; -import java.util.Date; -import java.util.List; -import java.util.Map; - -/** - * @author Anindya Chatterjee. - */ -@ToString -@EqualsAndHashCode -@Indices({ - @Index(value = "companyName") -}) -public class Company implements Serializable, Mappable { - @Id - @Getter - @Setter - private Long companyId; - - @Getter - @Setter - private String companyName; - - @Getter - @Setter - private Date dateCreated; - - @Getter - @Setter - private List departments; - - @Getter - @Setter - private Map> employeeRecord; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("companyId", companyId) - .put("companyName", companyName) - .put("dateCreated", dateCreated) - .put("departments", departments) - .put("employeeRecord", employeeRecord); - } - - @Override - @SuppressWarnings("unchecked") - public void read(NitriteMapper mapper, Document document) { - companyId = document.get("companyId", Long.class); - companyName = document.get("companyName", String.class); - dateCreated = document.get("dateCreated", Date.class); - departments = document.get("departments", List.class); - employeeRecord = document.get("employeeRecord", Map.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/DataGenerator.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/DataGenerator.java deleted file mode 100644 index c0a0352be..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/DataGenerator.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @author Anindya Chatterjee. - */ -public class DataGenerator { - private static final Random random = new Random(System.currentTimeMillis()); - private static final AtomicInteger counter = new AtomicInteger(random.nextInt()); - - private DataGenerator() {} - - public static Company generateCompanyRecord() { - Company company = new Company(); - company.setCompanyId(System.nanoTime() + counter.incrementAndGet()); - company.setCompanyName(randomCompanyName()); - company.setDateCreated(randomDate()); - List departments = departments(); - company.setDepartments(departments); - - Map> employeeRecord = new HashMap<>(); - for (String department : departments) { - employeeRecord.put(department, - generateEmployeeRecords(company, random.nextInt(20))); - } - company.setEmployeeRecord(employeeRecord); - return company; - } - - private static List generateEmployeeRecords(Company company, int count) { - List employeeList = new ArrayList<>(); - for (int i = 0; i < count; i++) { - Employee employee = generateEmployee(); - employee.setCompany(company); - employeeList.add(employee); - } - return employeeList; - } - - public static Employee generateEmployee() { - Employee employee = new Employee(); - employee.setEmpId(System.nanoTime() + counter.incrementAndGet()); - employee.setJoinDate(randomDate()); - employee.setAddress(UUID.randomUUID().toString().replace('-', ' ')); - - byte[] blob = new byte[random.nextInt(8000)]; - random.nextBytes(blob); - employee.setBlob(blob); - employee.setEmployeeNote(randomNote()); - - return employee; - } - - private static Date randomDate() { - return new Date(-946771200000L + - (Math.abs(random.nextLong()) % (70L * 365 * 24 * 60 * 60 * 1000))); - } - - public static Note randomNote() { - InputStream inputStream = ClassLoader.getSystemResourceAsStream("test.text"); - - assert inputStream != null; - try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) { - String strLine; - long line = random.nextInt(49); - int count = 0; - while ((strLine = br.readLine()) != null) { - if (count == line) { - Note note = new Note(); - note.setNoteId(line); - note.setText(strLine); - return note; - } - count++; - } - } catch (IOException e) { - // ignore - } - // ignore - return null; - } - - private static String randomCompanyName() { - InputStream inputStream = ClassLoader.getSystemResourceAsStream("english.stop"); - - assert inputStream != null; - try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) { - String strLine; - int line = random.nextInt(570); - int count = 0; - while ((strLine = br.readLine()) != null) { - if (count == line) { - return strLine + System.nanoTime() + " inc."; - } - count++; - } - } catch (IOException e) { - // ignore - } - // ignore - return null; - } - - private static List departments() { - return new ArrayList() {{ - add("dev"); - add("hr"); - add("qa"); - add("dev-ops"); - add("sales"); - add("marketing"); - add("design"); - add("support"); - }}; - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ElemMatch.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ElemMatch.java deleted file mode 100644 index dd0042ff1..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ElemMatch.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author Anindya Chatterjee - */ -@Data -public class ElemMatch implements Mappable { - private long id; - private String[] strArray; - private ProductScore[] productScores; - - @Override - public Document write(NitriteMapper mapper) { - List list = new ArrayList<>(); - if (productScores != null) { - for (ProductScore productScore : productScores) { - Document document = productScore.write(mapper); - list.add(document); - } - } - - return Document.createDocument("id", id) - .put("strArray", strArray) - .put("productScores", list); - } - - @Override - @SuppressWarnings("unchecked") - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Long.class); - strArray = document.get("strArray", String[].class); - List list = document.get("productScores", List.class); - if (list != null) { - productScores = new ProductScore[list.size()]; - for (int i = 0; i < list.size(); i++) { - productScores[i] = new ProductScore(); - productScores[i].read(mapper, list.get(i)); - } - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/Employee.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/Employee.java deleted file mode 100644 index 3da19271f..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/Employee.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.io.Serializable; -import java.util.Date; - -/** - * @author Anindya Chatterjee. - */ -@ToString -@EqualsAndHashCode -@Index(value = "joinDate", type = IndexType.NonUnique) -@Index(value = "address", type = IndexType.Fulltext) -@Index(value = "employeeNote.text", type = IndexType.Fulltext) -public class Employee implements Serializable, Mappable { - @Id - @Getter - @Setter - private Long empId; - - @Getter - @Setter - private Date joinDate; - - @Getter - @Setter - private String address; - - @Getter - @Setter - private transient Company company; - - @Getter - @Setter - private byte[] blob; - - @Getter - @Setter - private Note employeeNote; - - public Employee() { - } - - public Employee(Employee copy) { - empId = copy.empId; - joinDate = copy.joinDate; - address = copy.address; - company = copy.company; - blob = copy.blob; - employeeNote = copy.employeeNote; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("empId", empId) - .put("joinDate", joinDate) - .put("address", address) - .put("blob", blob) - .put("employeeNote", employeeNote != null ? employeeNote.write(mapper) : null); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - empId = document.get("empId", Long.class); - joinDate = document.get("joinDate", Date.class); - address = document.get("address", String.class); - blob = document.get("blob", byte[].class); - - if (document.get("employeeNote") != null) { - employeeNote = new Note(); - employeeNote.read(mapper, document.get("employeeNote", Document.class)); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/Note.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/Note.java deleted file mode 100644 index 24dacae30..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/Note.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.io.Serializable; - -/** - * @author Anindya Chatterjee. - */ -@EqualsAndHashCode -public class Note implements Serializable, Mappable { - @Getter - @Setter - private Long noteId; - @Getter - @Setter - private String text; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument().put("noteId", noteId).put("text", text); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - noteId = document.get("noteId", Long.class); - text = document.get("text", String.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ParentClass.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ParentClass.java deleted file mode 100644 index ccc9faab1..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ParentClass.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.util.Date; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@Index(value = "date") -public class ParentClass extends SuperDuperClass { - @Id - protected Long id; - private Date date; - - @Override - public Document write(NitriteMapper mapper) { - return super.write(mapper) - .put("id", id) - .put("date", date); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - super.read(mapper, document); - id = document.get("id", Long.class); - date = document.get("date", Date.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/PersonEntity.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/PersonEntity.java deleted file mode 100644 index 0e1a306a6..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/PersonEntity.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Entity; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; - -import java.util.Date; -import java.util.UUID; - -/** - * @author Anindya Chatterjee - */ -@Data -@Entity(value = "MyPerson", indices = { - @Index(value = "name", type = IndexType.Fulltext), - @Index(value = "status", type = IndexType.NonUnique) -}) -public class PersonEntity implements Mappable { - @Id - private String uuid; - private String name; - private String status; - private PersonEntity friend; - private Date dateCreated; - - public PersonEntity() { - this.uuid = UUID.randomUUID().toString(); - this.dateCreated = new Date(); - } - - public PersonEntity(String name) { - this.uuid = UUID.randomUUID().toString(); - this.name = name; - this.dateCreated = new Date(); - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("uuid", uuid) - .put("name", name) - .put("status", status) - .put("friend", friend != null ? friend.write(mapper) : null) - .put("dateCreated", dateCreated); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - if (document != null) { - uuid = document.get("uuid", String.class); - name = document.get("name", String.class); - status = document.get("status", String.class); - dateCreated = document.get("dateCreated", Date.class); - friend = new PersonEntity(); - friend.read(mapper, document.get("friend", Document.class)); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ProductScore.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ProductScore.java deleted file mode 100644 index 9075ae5f5..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/ProductScore.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -public class ProductScore implements Mappable { - private String product; - private int score; - - public ProductScore() { - } - - public ProductScore(String product, int score) { - this.product = product; - this.score = score; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("product", product) - .put("score", score); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - product = document.get("product", String.class); - score = document.get("score", Integer.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/RepeatableIndexTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/RepeatableIndexTest.java deleted file mode 100644 index 68e862c8e..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/RepeatableIndexTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee - */ -@Data -@Index(value = "firstName") -@Index(value = "age", type = IndexType.NonUnique) -@Index(value = "lastName", type = IndexType.Fulltext) -public class RepeatableIndexTest implements Mappable { - private String firstName; - private Integer age; - private String lastName; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("firstName", firstName) - .put("age", age) - .put("lastName", lastName); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - firstName = document.get("firstName", String.class); - age = document.get("age", Integer.class); - lastName = document.get("lastName", String.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/StressRecord.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/StressRecord.java deleted file mode 100644 index 471ae0964..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/StressRecord.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class StressRecord implements Mappable { - private String firstName; - private boolean processed; - private String lastName; - private boolean failed; - private String notes; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument().put("firstName", firstName) - .put("processed", processed) - .put("lastName", lastName) - .put("failed", failed) - .put("notes", notes); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - firstName = document.get("firstName", String.class); - processed = document.get("processed", Boolean.class); - lastName = document.get("lastName", String.class); - failed = document.get("failed", Boolean.class); - notes = document.get("notes", String.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/SubEmployee.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/SubEmployee.java deleted file mode 100644 index 8c845a616..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/SubEmployee.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.util.Date; - -/** - * @author Anindya Chatterjee. - */ -@EqualsAndHashCode -public class SubEmployee implements Mappable { - @Getter - @Setter - private Long empId; - - @Getter - @Setter - private Date joinDate; - - @Getter - @Setter - private String address; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("empId", empId) - .put("joinDate", joinDate) - .put("address", address); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - empId = document.get("empId", Long.class); - joinDate = document.get("joinDate", Date.class); - address = document.get("address", String.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/SuperDuperClass.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/SuperDuperClass.java deleted file mode 100644 index edb2f3767..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/SuperDuperClass.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@Index(value = "text", type = IndexType.Fulltext) -public class SuperDuperClass implements Mappable { - private String text; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("text", text); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - text = document.get("text", String.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithCircularReference.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithCircularReference.java deleted file mode 100644 index ea80f05ca..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithCircularReference.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithCircularReference { - private String name; - private WithCircularReference parent; -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithClassField.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithClassField.java deleted file mode 100644 index 5aa4c24f7..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithClassField.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithClassField implements Mappable { - @Id - private String name; - private Class clazz; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name) - .put("clazz", clazz); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - clazz = document.get("clazz", Class.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithCustomConstructor.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithCustomConstructor.java deleted file mode 100644 index 3f611bacd..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithCustomConstructor.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithCustomConstructor { - private String name; - private long number; - - public WithCustomConstructor(String name, long number) { - this.name = name; - this.number = number; - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithDateId.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithDateId.java deleted file mode 100644 index 16d113a2c..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithDateId.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.util.Date; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@EqualsAndHashCode -public class WithDateId implements Mappable { - private Date id; - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name) - .put("id", id); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - id = document.get("id", Date.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithEmptyStringId.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithEmptyStringId.java deleted file mode 100644 index abf40a668..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithEmptyStringId.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithEmptyStringId implements Mappable { - @Id - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithFinalField.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithFinalField.java deleted file mode 100644 index 5e2f50044..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithFinalField.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.exceptions.ObjectMappingException; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; - -/** - * @author Anindya Chatterjee. - */ -@Getter -public class WithFinalField implements Mappable { - private final long number; - @Setter - private String name; - - public WithFinalField() { - number = 2; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("name", name) - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - try { - Field field = getClass().getDeclaredField("number"); - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); - field.set(this, document.get("number", Long.class)); - } catch (Exception e) { - throw new ObjectMappingException("failed to set value"); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithNitriteId.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithNitriteId.java deleted file mode 100644 index 11c0dc1ad..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithNitriteId.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee - */ -@Data -public class WithNitriteId implements Mappable { - @Id - public NitriteId idField; - public String name; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("idField", idField) - .put("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - idField = document.get("idField", NitriteId.class); - name = document.get("name", String.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithNullId.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithNullId.java deleted file mode 100644 index f4208beac..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithNullId.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithNullId implements Mappable { - @Id - private String name; - private long number; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("name", name) - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - number = document.get("number", Long.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithObjectId.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithObjectId.java deleted file mode 100644 index b6efa556a..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithObjectId.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithObjectId implements Mappable { - @Id - private WithOutId withOutId; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("withOutId", withOutId); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - withOutId = document.get("withOutId", WithOutId.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithOutGetterSetter.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithOutGetterSetter.java deleted file mode 100644 index 607967bd3..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithOutGetterSetter.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.EqualsAndHashCode; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@EqualsAndHashCode -public class WithOutGetterSetter implements Mappable { - private String name; - private long number; - - public WithOutGetterSetter() { - name = "test"; - number = 2; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name) - .put("number", number); - - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - number = document.get("number", Long.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithOutId.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithOutId.java deleted file mode 100644 index 08cad426e..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithOutId.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithOutId implements Comparable, Mappable { - private String name; - private long number; - - @Override - public int compareTo(WithOutId o) { - return Long.compare(number, o.number); - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("name", name) - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - number = document.get("number", Long.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithPrivateConstructor.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithPrivateConstructor.java deleted file mode 100644 index 25df54331..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithPrivateConstructor.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.EqualsAndHashCode; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@EqualsAndHashCode -public class WithPrivateConstructor implements Mappable { - private String name; - private long number; - - private WithPrivateConstructor() { - name = "test"; - number = 2; - } - - public static WithPrivateConstructor create(final String name, final long number) { - WithPrivateConstructor obj = new WithPrivateConstructor(); - obj.number = number; - obj.name = name; - return obj; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name) - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - number = document.get("number", Long.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithPublicField.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithPublicField.java deleted file mode 100644 index 58cd082aa..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithPublicField.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -public class WithPublicField implements Mappable { - @Id - public String name; - public long number; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name) - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - number = document.get("number", Long.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithTransientField.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithTransientField.java deleted file mode 100644 index 7c634e44b..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/repository/data/WithTransientField.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithTransientField implements Mappable { - private transient String name; - @Id - private long number; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - number = document.get("number", Long.class); - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/transaction/TransactionCollectionTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/transaction/TransactionCollectionTest.java deleted file mode 100644 index a235b8dfd..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/transaction/TransactionCollectionTest.java +++ /dev/null @@ -1,770 +0,0 @@ -package org.dizitart.no2.transaction; - -import com.github.javafaker.Faker; -import org.dizitart.no2.collection.BaseCollectionTest; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.TransactionException; -import org.dizitart.no2.index.IndexType; -import org.junit.Test; - -import java.util.*; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.collection.UpdateOptions.updateOptions; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -public class TransactionCollectionTest extends BaseCollectionTest { - - @Test - public void testCommitInsert() { - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - - Document document = createDocument("firstName", "John"); - txCol.insert(document); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); - assertNotEquals(collection.find(where("firstName").eq("John")).size(), 1); - - transaction.commit(); - - assertEquals(collection.find(where("firstName").eq("John")).size(), 1); - } - } - } - - @Test - public void testRollbackInsert() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - NitriteCollection txCol = transaction.getCollection("test"); - - Document document = createDocument("firstName", "John"); - Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); - txCol.insert(document); - txCol.insert(document2); - - // just to create UniqueConstraintViolation for rollback - collection.insert(createDocument("firstName", "Jane")); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertNotEquals(collection.find(where("firstName").eq("John")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - } - } - } - - @Test - public void testCommitUpdate() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - document.put("lastName", "Doe"); - - txCol.update(where("firstName").eq("John"), document, updateOptions(true)); - - assertEquals(txCol.find(where("lastName").eq("Doe")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - - transaction.commit(); - - assertEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - } - } - } - - @Test - public void testRollbackUpdate() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.insert(createDocument("firstName", "Jane")); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - NitriteCollection txCol = transaction.getCollection("test"); - - Document document = createDocument("firstName", "John"); - Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); - txCol.update(where("firstName").eq("Jane"), document2); - txCol.insert(document); - - // just to create UniqueConstraintViolation for rollback - collection.insert(createDocument("firstName", "John")); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); - assertEquals(txCol.find(where("lastName").eq("Doe")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(collection.find(where("firstName").eq("Jane")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - } - } - } - - @Test - public void testCommitRemove() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - - txCol.remove(where("firstName").eq("John")); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 0); - assertEquals(collection.find(where("firstName").eq("John")).size(), 1); - - transaction.commit(); - - assertEquals(collection.find(where("firstName").eq("John")).size(), 0); - } - } - } - - @Test - public void testRollbackRemove() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - - txCol.remove(where("firstName").eq("John")); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 0); - assertEquals(collection.find(where("firstName").eq("John")).size(), 1); - - txCol.insert(createDocument("firstName", "Jane")); - collection.insert(createDocument("firstName", "Jane")); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(collection.find(where("firstName").eq("John")).size(), 1); - assertEquals(collection.find(where("firstName").eq("Jane")).size(), 1); - } - } - } - - @Test - public void testCommitCreateIndex() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - txCol.createIndex("firstName", indexOptions(IndexType.Fulltext)); - - assertTrue(txCol.hasIndex("firstName")); - assertFalse(collection.hasIndex("firstName")); - - transaction.commit(); - - assertTrue(collection.hasIndex("firstName")); - } - } - } - - @Test - public void testRollbackCreateIndex() { - Document document = createDocument("firstName", "John"); - Document document2 = createDocument("firstName", "Jane"); - collection.insert(document); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - - txCol.createIndex("firstName", indexOptions(IndexType.Unique)); - - assertTrue(txCol.hasIndex("firstName")); - assertFalse(collection.hasIndex("firstName")); - - txCol.insert(document2); - collection.insert(document2); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertFalse(collection.hasIndex("firstName")); - } - } - } - - @Test - public void testCommitClear() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - txCol.clear(); - - assertEquals(0, txCol.size()); - assertEquals(1, collection.size()); - - transaction.commit(); - - assertEquals(0, collection.size()); - } - } - } - - @Test - public void testRollbackClear() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - Document document = createDocument("firstName", "John"); - Document document2 = createDocument("firstName", "Jane"); - collection.insert(document); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - - txCol.clear(); - - assertEquals(0, txCol.size()); - assertEquals(1, collection.size()); - - txCol.insert(document2); - collection.insert(document2); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(2, collection.size()); - } - } - } - - @Test - public void testCommitDropIndex() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - txCol.dropIndex("firstName"); - - assertFalse(txCol.hasIndex("firstName")); - assertTrue(collection.hasIndex("firstName")); - - transaction.commit(); - - assertFalse(collection.hasIndex("firstName")); - } - } - } - - @Test - public void testRollbackDropIndex() { - Document document = createDocument("firstName", "John").put("lastName", "Doe"); - Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); - collection.insert(document); - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - txCol.dropIndex("lastName"); - - assertFalse(txCol.hasIndex("lastName")); - assertTrue(collection.hasIndex("lastName")); - - txCol.insert(document2); - collection.insert(document2); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertTrue(collection.hasIndex("lastName")); - } - } - } - - @Test - public void testCommitDropAllIndices() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("lastName", indexOptions(IndexType.Unique)); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - txCol.dropAllIndices(); - - assertFalse(txCol.hasIndex("firstName")); - assertFalse(txCol.hasIndex("lastName")); - assertTrue(collection.hasIndex("firstName")); - assertTrue(collection.hasIndex("lastName")); - - transaction.commit(); - - assertFalse(collection.hasIndex("firstName")); - assertFalse(collection.hasIndex("lastName")); - } - } - } - - @Test - public void testRollbackDropAllIndices() { - Document document = createDocument("firstName", "John").put("lastName", "Doe"); - collection.insert(document); - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - txCol.dropAllIndices(); - - assertFalse(txCol.hasIndex("firstName")); - assertFalse(txCol.hasIndex("lastName")); - assertTrue(collection.hasIndex("firstName")); - assertTrue(collection.hasIndex("lastName")); - - txCol.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); - collection.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertTrue(collection.hasIndex("firstName")); - assertTrue(collection.hasIndex("lastName")); - } - } - } - - @Test - public void testCommitDropCollection() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - txCol.drop(); - - boolean expectedException = false; - try { - assertEquals(0, txCol.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - assertEquals(1, collection.size()); - - transaction.commit(); - - expectedException = false; - try { - assertEquals(0, collection.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - } - } - } - - @Test - public void testRollbackDropCollection() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - - txCol.drop(); - - boolean expectedException = false; - try { - assertEquals(0, txCol.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - assertEquals(1, collection.size()); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(1, collection.size()); - } - } - } - - @Test - public void testCommitSetAttribute() { - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - - Attributes attributes = new Attributes(); - attributes.setAttributes(Collections.singletonMap("key", "value")); - txCol.setAttributes(attributes); - - assertNull(collection.getAttributes()); - - transaction.commit(); - - assertEquals("value", collection.getAttributes().get("key")); - } - } - } - - @Test - public void testRollbackSetAttribute() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - NitriteCollection txCol = transaction.getCollection("test"); - - Attributes attributes = new Attributes(); - Map map = new HashMap<>(); - map.put("key", "value"); - attributes.setAttributes(map); - txCol.setAttributes(attributes); - - txCol.insert(createDocument("firstName", "John")); - txCol.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); - - assertNull(collection.getAttributes()); - - // just to create UniqueConstraintViolation for rollback - collection.insert(createDocument("firstName", "Jane")); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertNull(collection.getAttributes().get("key")); - } - } - } - - @Test - public void testConcurrentInsertAndRemove() { - NitriteCollection collection = db.getCollection("test"); - collection.createIndex("firstName", indexOptions(IndexType.NonUnique)); - collection.createIndex("id", indexOptions(IndexType.Unique)); - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - final long fi = i; - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - NitriteCollection txCol = transaction.getCollection("test"); - - for (int j = 0; j < 10; j++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("lastName", faker.name().lastName()) - .put("id", j + (fi * 10)); - txCol.insert(document); - } - - txCol.remove(where("id").eq(2 + (fi * 10))); - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(90, collection.size()); - } - } - - @Test - public void testConcurrentInsert() { - NitriteCollection collection = db.getCollection("test"); - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - NitriteCollection txCol = transaction.getCollection("test"); - - for (int j = 0; j < 10; j++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("lastName", faker.name().lastName()); - txCol.insert(document); - } - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(100, collection.size()); - } - } - - @Test - public void testConcurrentUpdate() { - NitriteCollection collection = db.getCollection("test"); - for (int i = 0; i < 10; i++) { - Document document = createDocument("id", i); - collection.insert(document); - } - - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - NitriteCollection txCol = transaction.getCollection("test"); - - for (int j = 0; j < 10; j++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("lastName", faker.name().lastName()) - .put("id", j); - txCol.update(where("id").eq(j), document, updateOptions(true)); - } - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(10, collection.size()); - } - } - - @Test - public void testTransactionOnDifferentCollections() { - NitriteCollection col1 = db.getCollection("test1"); - NitriteCollection col2 = db.getCollection("test2"); - NitriteCollection col3 = db.getCollection("test3"); - col3.createIndex("id", indexOptions(IndexType.Unique)); - - Faker faker = new Faker(); - - try(Session session = db.createSession()) { - Transaction transaction = session.beginTransaction(); - - NitriteCollection test1 = transaction.getCollection("test1"); - NitriteCollection test2 = transaction.getCollection("test2"); - NitriteCollection test3 = transaction.getCollection("test3"); - - for (int i = 0; i < 10; i++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", i); - test1.insert(document); - - document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 10); - test2.insert(document); - - document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 20); - test3.insert(document); - } - - assertEquals(test1.size(), 10); - assertEquals(test2.size(), 10); - assertEquals(test3.size(), 10); - - assertEquals(col1.size(), 0); - assertEquals(col2.size(), 0); - assertEquals(col3.size(), 0); - - transaction.commit(); - - assertEquals(col1.size(), 10); - assertEquals(col2.size(), 10); - assertEquals(col3.size(), 10); - } - - - Transaction transaction = null; - try (Session session = db.createSession()) { - transaction = session.beginTransaction(); - - NitriteCollection test1 = transaction.getCollection("test1"); - NitriteCollection test2 = transaction.getCollection("test2"); - NitriteCollection test3 = transaction.getCollection("test3"); - - for (int i = 0; i < 10; i++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 30); - test1.insert(document); - - document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 40); - test2.insert(document); - - document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 50); - test3.insert(document); - } - - assertEquals(test1.size(), 20); - assertEquals(test2.size(), 20); - assertEquals(test3.size(), 20); - - assertEquals(col1.size(), 10); - assertEquals(col2.size(), 10); - assertEquals(col3.size(), 10); - - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", 52); - col3.insert(document); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - - assertEquals(col1.size(), 10); - assertEquals(col2.size(), 10); - assertEquals(col3.size(), 11); // last document added - } - } - - @Test(expected = TransactionException.class) - public void testFailureOnClosedTransaction() { - try(Session session = db.createSession()) { - Transaction transaction = session.beginTransaction(); - NitriteCollection col = transaction.getCollection("test"); - col.insert(createDocument("id", 1)); - transaction.commit(); - - col.insert(createDocument("id", 2)); - fail(); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/transaction/TransactionRepositoryTest.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/transaction/TransactionRepositoryTest.java deleted file mode 100644 index b5b947381..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/transaction/TransactionRepositoryTest.java +++ /dev/null @@ -1,808 +0,0 @@ -package org.dizitart.no2.transaction; - -import com.github.javafaker.Faker; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.TransactionException; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.repository.BaseObjectRepositoryTest; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.data.SubEmployee; -import org.junit.Test; - -import java.util.*; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -public class TransactionRepositoryTest extends BaseObjectRepositoryTest { - - @Test - public void testCommitInsert() { - ObjectRepository repository = db.getRepository(TxData.class); - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - TxData txData1 = new TxData(); - txData1.setId(1L); - txData1.setName("John"); - - txRepo.insert(txData1); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 1); - assertNotEquals(repository.find(where("name").eq("John")).size(), 1); - - transaction.commit(); - - assertEquals(repository.find(where("name").eq("John")).size(), 1); - } - } - } - - @Test - public void testRollbackInsert() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - TxData txData1 = new TxData(); - txData1.setId(1L); - txData1.setName("John"); - - TxData txData2 = new TxData(); - txData2.setId(2L); - txData2.setName("Jane"); - - txRepo.insert(txData1, txData2); - - txData2.setName("Molly"); - repository.insert(txData2); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 1); - assertEquals(repository.find(where("name").eq("John")).size(), 0); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(repository.find(where("name").eq("John")).size(), 0); - assertEquals(repository.find(where("name").eq("Molly")).size(), 1); - } - } - } - - @Test - public void testCommitUpdate() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(new TxData(1L, "John")); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - TxData txData1 = new TxData(1L, "Jane"); - txRepo.update(txData1, true); - - assertEquals(txRepo.find(where("name").eq("Jane")).size(), 1); - assertNotEquals(repository.find(where("name").eq("Jane")).size(), 1); - - transaction.commit(); - - assertEquals(repository.find(where("name").eq("Jane")).size(), 1); - } - } - } - - @Test - public void testRollbackUpdate() { - ObjectRepository repository = db.getRepository(TxData.class, "rollback"); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(new TxData(1L, "Jane")); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - ObjectRepository txRepo = transaction.getRepository(TxData.class, "rollback"); - - TxData txData1 = new TxData(); - txData1.setId(2L); - txData1.setName("John"); - - TxData txData2 = new TxData(); - txData2.setId(1L); - txData2.setName("Jane Doe"); - txRepo.update(txData2); - txRepo.insert(txData1); - - // just to create UniqueConstraintViolation for rollback - repository.insert(txData1); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 1); - assertEquals(txRepo.find(where("name").eq("Jane Doe")).size(), 1); - assertNotEquals(repository.find(where("name").eq("Jane Doe")).size(), 1); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(repository.find(where("name").eq("Jane")).size(), 1); - assertNotEquals(repository.find(where("name").eq("Jane Doe")).size(), 1); - } - } - } - - @Test - public void testCommitRemove() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - txRepo.remove(where("name").eq("John")); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 0); - assertEquals(repository.find(where("name").eq("John")).size(), 1); - - transaction.commit(); - - assertEquals(repository.find(where("name").eq("John")).size(), 0); - } - } - } - - @Test - public void testRollbackRemove() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - TxData txData1 = new TxData(1L, "John"); - repository.insert(txData1); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - txRepo.remove(where("name").eq("John")); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 0); - assertEquals(repository.find(where("name").eq("John")).size(), 1); - - TxData txData2 = new TxData(2L, "Jane"); - txRepo.insert(txData2); - repository.insert(txData2); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(repository.find(where("name").eq("John")).size(), 1); - assertEquals(repository.find(where("name").eq("Jane")).size(), 1); - } - } - } - - @Test - public void testCommitCreateIndex() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.createIndex("name", indexOptions(IndexType.Fulltext)); - - assertTrue(txRepo.hasIndex("name")); - assertFalse(repository.hasIndex("name")); - - transaction.commit(); - - assertTrue(repository.hasIndex("name")); - } - } - } - - @Test - public void testRollbackCreateIndex() { - TxData txData1 = new TxData(1L, "John"); - TxData txData2 = new TxData(2L, "Jane"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.createIndex("name", indexOptions(IndexType.Fulltext)); - - assertTrue(txRepo.hasIndex("name")); - assertFalse(repository.hasIndex("name")); - - txRepo.insert(txData2); - repository.insert(txData2); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertFalse(repository.hasIndex("name")); - } - } - } - - @Test - public void testCommitClear() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.clear(); - - assertEquals(0, txRepo.size()); - assertEquals(1, repository.size()); - - transaction.commit(); - - assertEquals(0, repository.size()); - } - } - } - - @Test - public void testRollbackClear() { - TxData txData1 = new TxData(1L, "John"); - TxData txData2 = new TxData(2L, "Jane"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.clear(); - - assertEquals(0, txRepo.size()); - assertEquals(1, repository.size()); - - txRepo.insert(txData2); - repository.insert(txData2); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(2, repository.size()); - } - } - } - - @Test - public void testCommitDropIndex() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.dropIndex("name"); - - assertFalse(txRepo.hasIndex("name")); - assertTrue(repository.hasIndex("name")); - - transaction.commit(); - - assertFalse(repository.hasIndex("name")); - } - } - } - - @Test - public void testRollbackDropIndex() { - TxData txData1 = new TxData(1L, "John"); - TxData txData2 = new TxData(2L, "Jane"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.dropIndex("name"); - - assertFalse(txRepo.hasIndex("name")); - assertTrue(repository.hasIndex("name")); - - txRepo.insert(txData2); - repository.insert(txData2); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertTrue(repository.hasIndex("name")); - } - } - } - - @Test - public void testCommitDropAllIndices() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.dropAllIndices(); - - assertFalse(txRepo.hasIndex("name")); - assertTrue(repository.hasIndex("name")); - - transaction.commit(); - - assertFalse(repository.hasIndex("name")); - } - } - } - - @Test - public void testRollbackDropAllIndices() { - TxData txData1 = new TxData(1L, "John"); - TxData txData2 = new TxData(2L, "Jane"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.dropAllIndices(); - - assertFalse(txRepo.hasIndex("name")); - assertTrue(repository.hasIndex("name")); - - txRepo.insert(txData2); - repository.insert(txData2); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertTrue(repository.hasIndex("name")); - } - } - } - - @Test - public void testCommitDropRepository() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.drop(); - - boolean expectedException = false; - try { - assertEquals(0, txRepo.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - assertEquals(1, repository.size()); - - transaction.commit(); - - expectedException = false; - try { - assertEquals(0, repository.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - } - } - } - - @Test - public void testRollbackDropRepository() { - TxData txData1 = new TxData(1L, "John"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.drop(); - - boolean expectedException = false; - try { - assertEquals(0, txRepo.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - assertEquals(1, repository.size()); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(1, repository.size()); - } - } - } - - @Test - public void testCommitSetAttribute() { - ObjectRepository repository = db.getRepository(TxData.class); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - Attributes attributes = new Attributes(); - attributes.setAttributes(Collections.singletonMap("key", "value")); - txRepo.setAttributes(attributes); - - assertNull(repository.getAttributes()); - - transaction.commit(); - - assertEquals("value", repository.getAttributes().get("key")); - } - } - } - - @Test - public void testRollbackSetAttribute() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - Attributes attributes = new Attributes(); - Map map = new HashMap<>(); - map.put("key", "value"); - attributes.setAttributes(map); - txRepo.setAttributes(attributes); - - txRepo.insert(new TxData(1L, "John")); - txRepo.insert(new TxData(2L, "Jane")); - - assertNull(repository.getAttributes()); - - // just to create UniqueConstraintViolation for rollback - repository.insert(new TxData(2L, "Jane")); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 1); - assertNotEquals(repository.find(where("name").eq("John")).size(), 1); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertNull(repository.getAttributes().get("key")); - } - } - } - - @Test - public void testConcurrentInsertAndRemove() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.NonUnique)); - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - final long fi = i; - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - for (long j = 0; j < 10; j++) { - TxData txData = new TxData(j + (fi * 10), faker.name().name()); - txRepo.insert(txData); - } - - txRepo.remove(where("id").eq(2L + (fi * 10))); - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(90, repository.size()); - } - } - - @Test - public void testConcurrentInsert() { - ObjectRepository repository = db.getRepository(TxData.class); - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - final long fi = i; - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - for (long j = 0; j < 10; j++) { - TxData txData = new TxData(j + (fi * 10), faker.name().name()); - txRepo.insert(txData); - } - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(100, repository.size()); - } - } - - @Test - public void testConcurrentUpdate() { - ObjectRepository repository = db.getRepository(TxData.class); - Faker faker = new Faker(); - for (long j = 0; j < 10; j++) { - TxData txData = new TxData(j, faker.name().name()); - repository.insert(txData); - } - - List> futures = new ArrayList<>(); - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - for (int j = 0; j < 10; j++) { - TxData txData = new TxData((long) j, faker.name().name()); - txRepo.update(where("id").eq(j), txData); - } - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(10, repository.size()); - } - } - - @Test - public void testTransactionOnDifferentRepositoriesAndCollections() { - ObjectRepository repo1 = db.getRepository(TxData.class); - ObjectRepository repo2 = db.getRepository(TxData.class, "2"); - ObjectRepository repo3 = db.getRepository(SubEmployee.class); - NitriteCollection col1 = db.getCollection("test1"); - col1.createIndex("id", indexOptions(IndexType.Unique)); - - Faker faker = new Faker(); - - try(Session session = db.createSession()) { - Transaction transaction = session.beginTransaction(); - - ObjectRepository txRepo1 = transaction.getRepository(TxData.class); - ObjectRepository txRepo2 = transaction.getRepository(TxData.class, "2"); - ObjectRepository txRepo3 = transaction.getRepository(SubEmployee.class); - NitriteCollection test1 = transaction.getCollection("test1"); - - for (long i = 0; i < 10; i++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", i); - test1.insert(document); - - TxData txData1 = new TxData(i, faker.name().name()); - txRepo1.insert(txData1); - - TxData txData2 = new TxData(i + 10, faker.name().name()); - txRepo2.insert(txData2); - - SubEmployee employee = new SubEmployee(); - employee.setAddress(faker.address().fullAddress()); - employee.setEmpId(i); - employee.setJoinDate(faker.date().birthday()); - txRepo3.insert(employee); - } - - assertEquals(test1.size(), 10); - assertEquals(txRepo1.size(), 10); - assertEquals(txRepo2.size(), 10); - assertEquals(txRepo3.size(), 10); - - assertEquals(col1.size(), 0); - assertEquals(repo1.size(), 0); - assertEquals(repo2.size(), 0); - assertEquals(repo3.size(), 0); - - transaction.commit(); - - assertEquals(col1.size(), 10); - assertEquals(repo1.size(), 10); - assertEquals(repo2.size(), 10); - assertEquals(repo3.size(), 10); - } - - Transaction transaction = null; - try (Session session = db.createSession()) { - transaction = session.beginTransaction(); - - ObjectRepository txRepo1 = transaction.getRepository(TxData.class); - ObjectRepository txRepo2 = transaction.getRepository(TxData.class, "2"); - ObjectRepository txRepo3 = transaction.getRepository(SubEmployee.class); - NitriteCollection test1 = transaction.getCollection("test1"); - - for (long i = 0; i < 10; i++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 10); - test1.insert(document); - - TxData txData1 = new TxData(i + 10, faker.name().name()); - txRepo1.insert(txData1); - - TxData txData2 = new TxData(i + 20, faker.name().name()); - txRepo2.insert(txData2); - - SubEmployee employee = new SubEmployee(); - employee.setAddress(faker.address().fullAddress()); - employee.setEmpId(i + 10); - employee.setJoinDate(faker.date().birthday()); - txRepo3.insert(employee); - } - - assertEquals(test1.size(), 20); - assertEquals(txRepo1.size(), 20); - assertEquals(txRepo2.size(), 20); - assertEquals(txRepo3.size(), 20); - - assertEquals(col1.size(), 10); - assertEquals(repo1.size(), 10); - assertEquals(repo2.size(), 10); - assertEquals(repo3.size(), 10); - - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", 12L); - col1.insert(document); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - - assertEquals(col1.size(), 11); // last doc added - assertEquals(repo1.size(), 10); - assertEquals(repo2.size(), 10); - assertEquals(repo3.size(), 10); - } - } - - @Test(expected = TransactionException.class) - public void testFailureOnClosedTransaction() { - try(Session session = db.createSession()) { - Transaction transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.insert(new TxData(1L, "John")); - transaction.commit(); - - txRepo.insert(new TxData(2L, "Jane")); - fail(); - } - } -} diff --git a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/transaction/TxData.java b/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/transaction/TxData.java deleted file mode 100644 index f5e7c02cf..000000000 --- a/nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/transaction/TxData.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.transaction; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -class TxData implements Mappable { - @Id - private Long id; - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("id", id) - .put("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Long.class); - name = document.get("name", String.class); - } -} diff --git a/nitrite-replication/build.gradle b/nitrite-replication/build.gradle index 86f2774b6..c6c6dfec0 100644 --- a/nitrite-replication/build.gradle +++ b/nitrite-replication/build.gradle @@ -52,9 +52,9 @@ dependencies { testImplementation project(path: ':nitrite-mvstore-adapter', configuration: 'default') testAnnotationProcessor "org.projectlombok:lombok:1.18.12" - testImplementation "jakarta.websocket:jakarta.websocket-api:1.1.2" - testImplementation "org.glassfish.tyrus:tyrus-server:1.17" - testImplementation "org.glassfish.tyrus:tyrus-container-grizzly-server:1.17" + testImplementation "jakarta.websocket:jakarta.websocket-api:2.0.0" + testImplementation "org.glassfish.tyrus:tyrus-server:2.0.0" + testImplementation "org.glassfish.tyrus:tyrus-container-grizzly-server:2.0.0" testImplementation "org.awaitility:awaitility:4.0.3" testImplementation "org.apache.logging.log4j:log4j-slf4j-impl:2.13.3" testImplementation "org.apache.logging.log4j:log4j-core:2.13.3" diff --git a/nitrite-replication/src/main/java/org/dizitart/no2/sync/MessageDispatcher.java b/nitrite-replication/src/main/java/org/dizitart/no2/sync/MessageDispatcher.java index 9286f6745..a279130d4 100644 --- a/nitrite-replication/src/main/java/org/dizitart/no2/sync/MessageDispatcher.java +++ b/nitrite-replication/src/main/java/org/dizitart/no2/sync/MessageDispatcher.java @@ -34,8 +34,8 @@ */ @Slf4j class MessageDispatcher implements DataGateSocketListener, AutoCloseable { - private ReplicationTemplate replicationTemplate; - private MessageTransformer transformer; + private final ReplicationTemplate replicationTemplate; + private final MessageTransformer transformer; private ExecutorService executorService; public MessageDispatcher(Config config, ReplicationTemplate replicationTemplate) { diff --git a/nitrite-replication/src/main/java/org/dizitart/no2/sync/MessageTemplate.java b/nitrite-replication/src/main/java/org/dizitart/no2/sync/MessageTemplate.java index 937eb8d38..89e1f0062 100644 --- a/nitrite-replication/src/main/java/org/dizitart/no2/sync/MessageTemplate.java +++ b/nitrite-replication/src/main/java/org/dizitart/no2/sync/MessageTemplate.java @@ -25,8 +25,8 @@ */ @Slf4j public class MessageTemplate implements AutoCloseable { - private Config config; - private ReplicationTemplate replica; + private final Config config; + private final ReplicationTemplate replica; private DataGateSocket dataGateSocket; private MessageDispatcher dispatcher; diff --git a/nitrite-replication/src/main/java/org/dizitart/no2/sync/Replica.java b/nitrite-replication/src/main/java/org/dizitart/no2/sync/Replica.java index 0cde3dce7..d8417fdd2 100644 --- a/nitrite-replication/src/main/java/org/dizitart/no2/sync/Replica.java +++ b/nitrite-replication/src/main/java/org/dizitart/no2/sync/Replica.java @@ -26,7 +26,7 @@ */ @Slf4j public final class Replica implements AutoCloseable { - private ReplicationTemplate replicationTemplate; + private final ReplicationTemplate replicationTemplate; Replica(Config config) { this.replicationTemplate = new ReplicationTemplate(config); diff --git a/nitrite-replication/src/main/java/org/dizitart/no2/sync/ReplicationTemplate.java b/nitrite-replication/src/main/java/org/dizitart/no2/sync/ReplicationTemplate.java index 53ecd7f00..ac7feea96 100644 --- a/nitrite-replication/src/main/java/org/dizitart/no2/sync/ReplicationTemplate.java +++ b/nitrite-replication/src/main/java/org/dizitart/no2/sync/ReplicationTemplate.java @@ -47,7 +47,7 @@ @Slf4j @Getter public class ReplicationTemplate implements ReplicationOperation { - private Config config; + private final Config config; private MessageFactory messageFactory; private MessageTemplate messageTemplate; private LastWriteWinMap crdt; @@ -76,7 +76,7 @@ public class ReplicationTemplate implements ReplicationOperation { public ReplicationTemplate(Config config) { this.config = config; - init(); + initialize(); } public void connect() { @@ -186,7 +186,7 @@ public void collectGarbage(Long ttl) { } } - private void init() { + private void initialize() { this.messageFactory = new MessageFactory(); this.connected = new AtomicBoolean(false); this.exchangeFlag = new AtomicBoolean(false); diff --git a/nitrite-replication/src/main/java/org/dizitart/no2/sync/net/DataGateSocket.java b/nitrite-replication/src/main/java/org/dizitart/no2/sync/net/DataGateSocket.java index 5bed77b4f..d8e61713e 100644 --- a/nitrite-replication/src/main/java/org/dizitart/no2/sync/net/DataGateSocket.java +++ b/nitrite-replication/src/main/java/org/dizitart/no2/sync/net/DataGateSocket.java @@ -24,6 +24,7 @@ import org.dizitart.no2.sync.Config; import org.dizitart.no2.sync.ReplicationException; import org.dizitart.no2.sync.message.DataGateMessage; +import org.jetbrains.annotations.NotNull; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; @@ -44,24 +45,22 @@ public class DataGateSocket { private final static int RECONNECT_INTERVAL = 10 * 1000; private final static long RECONNECT_MAX_TIME = 120 * 1000; - + private final OkHttpClient httpClient; + private final Request request; + private final Lock lock; + private final ObjectMapper objectMapper; + private final Config config; + private final Callable networkConnectivityChecker; private WebSocket mWebSocket; - private OkHttpClient httpClient; - private Request request; private int currentStatus = Status.DISCONNECTED; private boolean manualClose; private DataGateSocketListener listener; - private Lock lock; private int reconnectCount = 0; private Timer reconnectTimer; - private ObjectMapper objectMapper; - private Config config; private CountDownLatch latch; - private Callable networkConnectivityChecker; - - private WebSocketListener webSocketListener = new WebSocketListener() { + private final WebSocketListener webSocketListener = new WebSocketListener() { @Override - public void onOpen(WebSocket webSocket, final Response response) { + public void onOpen(@NotNull WebSocket webSocket, @NotNull final Response response) { mWebSocket = webSocket; setCurrentStatus(Status.CONNECTED); if (latch != null) { @@ -75,35 +74,35 @@ public void onOpen(WebSocket webSocket, final Response response) { } @Override - public void onMessage(WebSocket webSocket, final String text) { + public void onMessage(@NotNull WebSocket webSocket, @NotNull final String text) { if (listener != null) { listener.onMessage(text); } } @Override - public void onMessage(WebSocket webSocket, ByteString bytes) { + public void onMessage(@NotNull WebSocket webSocket, @NotNull ByteString bytes) { if (listener != null) { listener.onMessage(bytes); } } @Override - public void onClosing(WebSocket webSocket, int code, String reason) { + public void onClosing(@NotNull WebSocket webSocket, int code, @NotNull String reason) { if (listener != null) { listener.onClosing(code, reason); } } @Override - public void onClosed(WebSocket webSocket, int code, String reason) { + public void onClosed(@NotNull WebSocket webSocket, int code, @NotNull String reason) { if (listener != null) { listener.onClosed(code, reason); } } @Override - public void onFailure(WebSocket webSocket, Throwable t, Response response) { + public void onFailure(@NotNull WebSocket webSocket, @NotNull Throwable t, Response response) { if (listener != null) { listener.onFailure(t, response); } @@ -172,7 +171,9 @@ private void initWebSocket() { lock.lockInterruptibly(); try { latch = new CountDownLatch(1); - httpClient.newWebSocket(request, webSocketListener); + if (httpClient != null) { + httpClient.newWebSocket(request, webSocketListener); + } latch.await(); } finally { lock.unlock(); diff --git a/nitrite-replication/src/test/java/org/dizitart/no2/integration/ReplicaTest.java b/nitrite-replication/src/test/java/org/dizitart/no2/integration/ReplicaTest.java index fe63cbba9..4e1e33252 100644 --- a/nitrite-replication/src/test/java/org/dizitart/no2/integration/ReplicaTest.java +++ b/nitrite-replication/src/test/java/org/dizitart/no2/integration/ReplicaTest.java @@ -22,11 +22,11 @@ import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.NitriteCollection; import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.integration.server.Repository; +import org.dizitart.no2.integration.server.SimpleDataGateServer; import org.dizitart.no2.sync.Replica; import org.dizitart.no2.sync.ReplicationTemplate; import org.dizitart.no2.sync.crdt.LastWriteWinMap; -import org.dizitart.no2.integration.server.Repository; -import org.dizitart.no2.integration.server.SimpleDataGateServer; import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -56,14 +56,13 @@ @Slf4j public class ReplicaTest { private static SimpleDataGateServer server; + @Rule + public Retry retry = new Retry(3); private String dbFile; private ExecutorService executorService; private Repository repository; private Nitrite db; - @Rule - public Retry retry = new Retry(3); - public static String getRandomTempDbFile() { String dataDir = System.getProperty("java.io.tmpdir") + File.separator + "nitrite" + File.separator + "data"; File file = new File(dataDir); @@ -103,9 +102,10 @@ public void testSingleUserSingleReplica() { db = createDb(dbFile); NitriteCollection collection = db.getCollection("testSingleUserSingleReplica"); - Document document = createDocument().put("firstName", "Anindya") - .put("lastName", "Chatterjee") - .put("address", createDocument("street", "1234 Abcd Street") + Document document = createDocument() + .put("firstName", "Anindya") + .put("lastName", "Chatterjee") + .put("address", createDocument("street", "1234 Abcd Street") .put("pin", 123456)); collection.insert(document); diff --git a/nitrite-replication/src/test/java/org/dizitart/no2/integration/server/Repository.java b/nitrite-replication/src/test/java/org/dizitart/no2/integration/server/Repository.java index 62412847e..bfc433ce9 100644 --- a/nitrite-replication/src/test/java/org/dizitart/no2/integration/server/Repository.java +++ b/nitrite-replication/src/test/java/org/dizitart/no2/integration/server/Repository.java @@ -16,11 +16,11 @@ package org.dizitart.no2.integration.server; +import jakarta.websocket.Session; import lombok.Data; import org.dizitart.no2.Nitrite; import org.dizitart.no2.sync.crdt.LastWriteWinMap; -import javax.websocket.Session; import java.util.*; import java.util.concurrent.ConcurrentHashMap; diff --git a/nitrite-replication/src/test/java/org/dizitart/no2/integration/server/SimpleDataGateEndpoint.java b/nitrite-replication/src/test/java/org/dizitart/no2/integration/server/SimpleDataGateEndpoint.java index 5ac758609..f5b2e925c 100644 --- a/nitrite-replication/src/test/java/org/dizitart/no2/integration/server/SimpleDataGateEndpoint.java +++ b/nitrite-replication/src/test/java/org/dizitart/no2/integration/server/SimpleDataGateEndpoint.java @@ -18,6 +18,9 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.websocket.*; +import jakarta.websocket.server.PathParam; +import jakarta.websocket.server.ServerEndpoint; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.dizitart.no2.collection.NitriteCollection; @@ -30,9 +33,6 @@ import org.dizitart.no2.sync.crdt.LastWriteWinState; import org.dizitart.no2.sync.message.*; -import javax.websocket.*; -import javax.websocket.server.PathParam; -import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.*; diff --git a/nitrite-replication/src/test/java/org/dizitart/no2/integration/server/SimpleDataGateServer.java b/nitrite-replication/src/test/java/org/dizitart/no2/integration/server/SimpleDataGateServer.java index 1cb3e1df6..3279f3aec 100644 --- a/nitrite-replication/src/test/java/org/dizitart/no2/integration/server/SimpleDataGateServer.java +++ b/nitrite-replication/src/test/java/org/dizitart/no2/integration/server/SimpleDataGateServer.java @@ -23,9 +23,9 @@ * @author Anindya Chatterjee */ public class SimpleDataGateServer { - private int port; + private final int port; private Server server; - private Repository repository; + private final Repository repository; public SimpleDataGateServer(int port) { this.port = port; diff --git a/nitrite-rocksdb-adapter/build.gradle b/nitrite-rocksdb-adapter/build.gradle index c979cfb35..0604644b9 100644 --- a/nitrite-rocksdb-adapter/build.gradle +++ b/nitrite-rocksdb-adapter/build.gradle @@ -38,6 +38,7 @@ dependencies { testImplementation "uk.co.jemos.podam:podam:7.2.5.RELEASE" testImplementation "com.github.javafaker:javafaker:1.0.2" testImplementation "junit:junit:4.13.1" + testImplementation "org.mockito:mockito-core:3.9.0" testImplementation "org.apache.lucene:lucene-core:8.6.3" testImplementation "org.apache.lucene:lucene-analyzers-common:8.6.3" testImplementation "org.apache.lucene:lucene-queryparser:8.6.3" diff --git a/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/EntrySet.java b/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/EntrySet.java index 68fe5abb1..764952621 100644 --- a/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/EntrySet.java +++ b/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/EntrySet.java @@ -12,18 +12,20 @@ class EntrySet implements Iterable> { private final ColumnFamilyHandle columnFamilyHandle; private final Class keyType; private final Class valueType; + private final boolean reverse; public EntrySet(RocksDB rocksDB, ColumnFamilyHandle columnFamilyHandle, - ObjectFormatter objectFormatter, Class keyType, Class valueType) { + ObjectFormatter objectFormatter, Class keyType, + Class valueType, boolean reverse) { this.rocksDB = rocksDB; this.columnFamilyHandle = columnFamilyHandle; this.objectFormatter = objectFormatter; this.keyType = keyType; this.valueType = valueType; + this.reverse = reverse; } @Override - @SuppressWarnings("NullableProblems") public Iterator> iterator() { return new EntryIterator(); } @@ -33,7 +35,11 @@ private class EntryIterator implements Iterator> { public EntryIterator() { rawEntryIterator = rocksDB.newIterator(columnFamilyHandle); - rawEntryIterator.seekToFirst(); + if (reverse) { + rawEntryIterator.seekToLast(); + } else { + rawEntryIterator.seekToFirst(); + } } @Override @@ -55,7 +61,11 @@ public Pair next() { K key = (K) objectFormatter.decodeKey(rawEntryIterator.key(), keyType); try { V value = (V) objectFormatter.decode(rawEntryIterator.value(), valueType); - rawEntryIterator.next(); + if (reverse) { + rawEntryIterator.prev(); + } else { + rawEntryIterator.next(); + } return new Pair<>(key, value); } catch (Exception e) { System.out.println(new String(rawEntryIterator.value())); diff --git a/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/KeySet.java b/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/KeySet.java index f234936b2..73dd687ff 100644 --- a/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/KeySet.java +++ b/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/KeySet.java @@ -21,7 +21,6 @@ public KeySet(RocksDB rocksDB, ColumnFamilyHandle columnFamilyHandle, ObjectForm } @Override - @SuppressWarnings("NullableProblems") public Iterator iterator() { return new KeyIterator(); } diff --git a/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/RocksDBMap.java b/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/RocksDBMap.java index 37870e88d..874c037da 100644 --- a/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/RocksDBMap.java +++ b/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/RocksDBMap.java @@ -3,14 +3,13 @@ import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import org.dizitart.no2.common.tuples.Pair; import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.tuples.Pair; import org.dizitart.no2.exceptions.NitriteIOException; import org.dizitart.no2.rocksdb.formatter.ObjectFormatter; import org.dizitart.no2.store.NitriteMap; import org.dizitart.no2.store.NitriteStore; import org.rocksdb.ColumnFamilyHandle; -import org.rocksdb.ComparatorOptions; import org.rocksdb.RocksDB; import org.rocksdb.RocksIterator; import org.rocksdb.util.BytewiseComparator; @@ -136,7 +135,7 @@ public V remove(K k) { } @Override - public RecordStream keySet() { + public RecordStream keys() { return RecordStream.fromIterable(new KeySet<>(rocksDB, columnFamilyHandle, objectFormatter, getKeyType())); } @@ -208,7 +207,13 @@ public V putIfAbsent(K k, V v) { @Override public RecordStream> entries() { return RecordStream.fromIterable(new EntrySet<>(rocksDB, columnFamilyHandle, - objectFormatter, getKeyType(), getValueType())); + objectFormatter, getKeyType(), getValueType(), false)); + } + + @Override + public RecordStream> reversedEntries() { + return RecordStream.fromIterable(new EntrySet<>(rocksDB, columnFamilyHandle, + objectFormatter, getKeyType(), getValueType(), true)); } @Override @@ -326,7 +331,7 @@ public boolean isEmpty() { @Override public void drop() { - store.removeMap(mapName); + store.removeMap(getName()); close(); } @@ -335,13 +340,11 @@ private void initialize() { this.objectFormatter = store.getStoreConfig().objectFormatter(); this.columnFamilyHandle = reference.getOrCreateColumnFamily(getName()); this.rocksDB = reference.getRocksDB(); - this.bytewiseComparator = new BytewiseComparator(new ComparatorOptions()); - this.reference.addComparator(bytewiseComparator); + this.bytewiseComparator = this.reference.getDbComparator(); } @Override public void close() { - bytewiseComparator.close(); - columnFamilyHandle.close(); + store.closeMap(getName()); } } diff --git a/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/RocksDBModule.java b/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/RocksDBModule.java index eb151697a..6e15fc13b 100644 --- a/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/RocksDBModule.java +++ b/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/RocksDBModule.java @@ -2,12 +2,14 @@ import lombok.AccessLevel; import lombok.Setter; -import org.dizitart.no2.module.NitritePlugin; +import org.dizitart.no2.common.module.NitritePlugin; import org.dizitart.no2.store.NitriteStore; import org.dizitart.no2.store.StoreModule; import java.util.Set; +import static org.dizitart.no2.common.util.Iterables.setOf; + public class RocksDBModule implements StoreModule { @Setter(AccessLevel.PACKAGE) diff --git a/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/RocksDBReference.java b/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/RocksDBReference.java index 8071aebbd..4bbd9437c 100644 --- a/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/RocksDBReference.java +++ b/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/RocksDBReference.java @@ -16,10 +16,12 @@ package org.dizitart.no2.rocksdb; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.dizitart.no2.exceptions.NitriteIOException; import org.rocksdb.*; +import org.rocksdb.util.BytewiseComparator; import java.nio.charset.StandardCharsets; import java.util.ArrayList; @@ -30,32 +32,34 @@ /** * @author Anindya Chatterjee */ -@Data @Slf4j +@Getter +@Setter public class RocksDBReference implements AutoCloseable { private Options options; private DBOptions dbOptions; private ColumnFamilyOptions columnFamilyOptions; private RocksDB rocksDB; + private BytewiseComparator dbComparator; private List columnFamilyDescriptors; private Map columnFamilyHandleRegistry; - private List dbComparators; public RocksDBReference() { this.columnFamilyDescriptors = new ArrayList<>(); this.columnFamilyHandleRegistry = new ConcurrentHashMap<>(); - this.dbComparators = new ArrayList<>(); + this.dbComparator = null; } @Override public void close() throws RocksDBException { + // if nitrite maps are already closed, this will affect nothing columnFamilyHandleRegistry.values().forEach(AbstractImmutableNativeReference::close); columnFamilyHandleRegistry.clear(); rocksDB.closeE(); dbOptions.close(); - dbComparators.forEach(AbstractImmutableNativeReference::close); + dbComparator.close(); columnFamilyOptions.close(); options.close(); } @@ -90,7 +94,20 @@ public void dropColumnFamily(String mapName) { } } - public void addComparator(AbstractComparator comparator) { - dbComparators.add(comparator); + public void closeColumnFamily(String mapName) { + if (columnFamilyHandleRegistry.containsKey(mapName)) { + ColumnFamilyHandle handle = columnFamilyHandleRegistry.get(mapName); + handle.close(); + columnFamilyHandleRegistry.remove(mapName); + } + } + + public BytewiseComparator getDbComparator() { + // delayed initialization, otherwise initializing + // it in ctor is throwing java.lang.UnsatisfiedLinkError + if (dbComparator == null) { + dbComparator = new BytewiseComparator(new ComparatorOptions()); + } + return dbComparator; } } diff --git a/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/RocksDBStore.java b/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/RocksDBStore.java index 9a2002160..11dd021ca 100644 --- a/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/RocksDBStore.java +++ b/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/RocksDBStore.java @@ -11,6 +11,7 @@ import org.dizitart.no2.store.NitriteRTree; import org.dizitart.no2.store.events.StoreEventListener; import org.dizitart.no2.store.events.StoreEvents; +import org.rocksdb.RocksDB; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -66,12 +67,18 @@ public void commit() { } @Override - public void close() { + public void close() throws Exception { try { if (!closed.get()) { + // close nitrite maps + for (NitriteMap nitriteMap : nitriteMapRegistry.values()) { + nitriteMap.close(); + } + reference.close(); closed.compareAndSet(false, true); } + alert(StoreEvents.Closed); } catch (Exception e) { log.error("Error while closing the database", e); @@ -107,6 +114,11 @@ public NitriteMap openMap(String mapName, } } + @Override + public void closeMap(String mapName) { + nitriteMapRegistry.remove(mapName); + } + @Override public void removeMap(String mapName) { reference.dropColumnFamily(mapName); @@ -120,6 +132,11 @@ public NitriteRTree openRTree(Strin throw new InvalidOperationException("rtree not supported on rocksdb store"); } + @Override + public void closeRTree(String rTreeName) { + throw new InvalidOperationException("rtree not supported on rocksdb store"); + } + @Override public void removeRTree(String mapName) { throw new InvalidOperationException("rtree not supported on rocksdb store"); @@ -139,6 +156,7 @@ private void initEventBus() { } private static String getRocksDbVersion() { - return "6.11.4"; + RocksDB.Version version = RocksDB.rocksdbVersion(); + return version.toString(); } } diff --git a/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/ValueSet.java b/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/ValueSet.java index a74f6b71e..138b82660 100644 --- a/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/ValueSet.java +++ b/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/ValueSet.java @@ -13,7 +13,8 @@ class ValueSet implements Iterable { private final ColumnFamilyHandle columnFamilyHandle; private final Class valueType; - public ValueSet(RocksDB rocksDB, ColumnFamilyHandle columnFamilyHandle, ObjectFormatter objectFormatter, Class valueType) { + public ValueSet(RocksDB rocksDB, ColumnFamilyHandle columnFamilyHandle, + ObjectFormatter objectFormatter, Class valueType) { this.rocksDB = rocksDB; this.columnFamilyHandle = columnFamilyHandle; this.objectFormatter = objectFormatter; @@ -21,7 +22,6 @@ public ValueSet(RocksDB rocksDB, ColumnFamilyHandle columnFamilyHandle, ObjectFo } @Override - @SuppressWarnings("NullableProblems") public Iterator iterator() { return new ValueIterator(); } diff --git a/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/formatter/KryoObjectFormatter.java b/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/formatter/KryoObjectFormatter.java index 1bce3285e..d8399a37d 100644 --- a/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/formatter/KryoObjectFormatter.java +++ b/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/formatter/KryoObjectFormatter.java @@ -126,6 +126,5 @@ private void registerInternalSerializers() { NitriteSerializers.registerAll(this); DefaultJavaSerializers.registerAll(this); DefaultTimeKeySerializers.registerAll(this); -// DefaultNumberKeySerializers.registerAll(this); } } diff --git a/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/formatter/NitriteSerializers.java b/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/formatter/NitriteSerializers.java index 98146e61c..334f08980 100644 --- a/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/formatter/NitriteSerializers.java +++ b/nitrite-rocksdb-adapter/src/main/java/org/dizitart/no2/rocksdb/formatter/NitriteSerializers.java @@ -8,11 +8,15 @@ import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.collection.meta.Attributes; +import org.dizitart.no2.common.Fields; import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.index.IndexEntry; +import org.dizitart.no2.index.DBValue; +import org.dizitart.no2.index.IndexDescriptor; import org.dizitart.no2.index.IndexMeta; import org.dizitart.no2.store.UserCredential; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; @@ -87,39 +91,39 @@ private static class IndexMetaSerializer extends Serializer { @Override public void write(Kryo kryo, Output output, IndexMeta object) { - kryo.writeObject(output, object.getIndexEntry()); + kryo.writeObject(output, object.getIndexDescriptor()); output.writeString(object.getIndexMap()); output.writeBoolean(object.getIsDirty().get()); } @Override public IndexMeta read(Kryo kryo, Input input, Class type) { - IndexEntry indexEntry = kryo.readObject(input, IndexEntry.class); + IndexDescriptor indexDescriptor = kryo.readObject(input, IndexDescriptor.class); String indexMap = input.readString(); boolean isDirty = input.readBoolean(); IndexMeta indexMeta = new IndexMeta(); - indexMeta.setIndexEntry(indexEntry); + indexMeta.setIndexDescriptor(indexDescriptor); indexMeta.setIndexMap(indexMap); indexMeta.setIsDirty(new AtomicBoolean(isDirty)); return indexMeta; } } - private static class IndexEntrySerializer extends Serializer { + private static class IndexDescriptorSerializer extends Serializer { @Override - public void write(Kryo kryo, Output output, IndexEntry object) { + public void write(Kryo kryo, Output output, IndexDescriptor object) { + kryo.writeObject(output, object.getIndexFields()); output.writeString(object.getCollectionName()); - output.writeString(object.getField()); output.writeString(object.getIndexType()); } @Override - public IndexEntry read(Kryo kryo, Input input, Class type) { + public IndexDescriptor read(Kryo kryo, Input input, Class type) { + Fields fields = kryo.readObject(input, Fields.class); String collectionName = input.readString(); - String field = input.readString(); String indexType = input.readString(); - return new IndexEntry(indexType, field, collectionName); + return new IndexDescriptor(indexType, fields, collectionName); } } @@ -166,13 +170,43 @@ public Attributes read(Kryo kryo, Input input, Class type) { } } + private static class FieldsSerializer extends Serializer { + @Override + public void write(Kryo kryo, Output output, Fields object) { + kryo.writeObject(output, object.getFieldNames()); + } + + @Override + @SuppressWarnings("unchecked") + public Fields read(Kryo kryo, Input input, Class type) { + List fieldNames = (List) kryo.readObject(input, ArrayList.class); + return Fields.withNames(fieldNames.toArray(new String[0])); + } + } + + private static class DBValueSerializer extends Serializer { + + @Override + public void write(Kryo kryo, Output output, DBValue object) { + kryo.writeClassAndObject(output, object.getValue()); + } + + @Override + public DBValue read(Kryo kryo, Input input, Class type) { + Object value = kryo.readClassAndObject(input); + return new DBValue((Comparable) value); + } + } + public static void registerAll(KryoObjectFormatter kryoObjectFormatter) { kryoObjectFormatter.registerSerializer(NitriteId.class, new NitriteIdSerializer()); kryoObjectFormatter.registerSerializer(Pair.class, new PairSerializer()); kryoObjectFormatter.registerSerializer(Document.class, new DocumentSerializer()); kryoObjectFormatter.registerSerializer(IndexMeta.class, new IndexMetaSerializer()); - kryoObjectFormatter.registerSerializer(IndexEntry.class, new IndexEntrySerializer()); + kryoObjectFormatter.registerSerializer(IndexDescriptor.class, new IndexDescriptorSerializer()); kryoObjectFormatter.registerSerializer(UserCredential.class, new UserCredentialSerializer()); kryoObjectFormatter.registerSerializer(Attributes.class, new AttributesSerializer()); + kryoObjectFormatter.registerSerializer(Fields.class, new FieldsSerializer()); + kryoObjectFormatter.registerSerializer(DBValue.class, new DBValueSerializer()); } } diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/NitriteTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/NitriteTest.java new file mode 100644 index 000000000..d22bd411d --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/NitriteTest.java @@ -0,0 +1,481 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.FindOptions; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.UpdateOptions; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.common.concurrent.ThreadPoolManager; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.exceptions.NitriteIOException; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.integration.TestUtil; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; +import org.dizitart.no2.repository.annotations.Indices; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import uk.co.jemos.podam.api.PodamFactory; +import uk.co.jemos.podam.api.PodamFactoryImpl; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Locale; +import java.util.Random; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.common.Constants.INTERNAL_NAME_SEPARATOR; +import static org.dizitart.no2.common.Constants.META_MAP_NAME; +import static org.dizitart.no2.filters.Filter.ALL; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class NitriteTest { + private Nitrite db; + private NitriteCollection collection; + private SimpleDateFormat simpleDateFormat; + private final String fileName = getRandomTempDbFile(); + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() throws ParseException { + db = TestUtil.createDb(fileName, "test-user", "test-password"); + + simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); + + Document doc1 = createDocument("firstName", "fn1") + .put("lastName", "ln1") + .put("birthDay", simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + .put("data", new byte[]{1, 2, 3}) + .put("body", "a quick brown fox jump over the lazy dog"); + Document doc2 = createDocument("firstName", "fn2") + .put("lastName", "ln2") + .put("birthDay", simpleDateFormat.parse("2010-06-12T16:02:48.440Z")) + .put("data", new byte[]{3, 4, 3}) + .put("body", "hello world from nitrite"); + Document doc3 = createDocument("firstName", "fn3") + .put("lastName", "ln2") + .put("birthDay", simpleDateFormat.parse("2014-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + + collection = db.getCollection("test"); + collection.remove(ALL); + + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "firstName"); + collection.insert(doc1, doc2, doc3); + } + + @After + public void tearDown() { + if (collection.isOpen()) { + collection.remove(ALL); + collection.close(); + } + if (db != null && !db.isClosed()) { + try { + db.close(); + } catch (NitriteIOException ignore) { + } + } + deleteDb(fileName); + } + + @Test + public void testListCollectionNames() { + Set collectionNames = db.listCollectionNames(); + assertEquals(collectionNames.size(), 1); + } + + @Test + public void testListRepositories() { + db.getRepository(getClass()); + Set repositories = db.listRepositories(); + assertEquals(repositories.size(), 1); + } + + @Test + public void testHasCollection() { + assertTrue(db.hasCollection("test")); + assertFalse(db.hasCollection("lucene" + INTERNAL_NAME_SEPARATOR + "test")); + } + + @Test + public void testHasRepository() { + db.getRepository(getClass()); + assertTrue(db.hasRepository(getClass())); + assertFalse(db.hasRepository(String.class)); + } + + + @Test + public void testReopen() throws ParseException { + assertNotNull(db); + NitriteCollection testCollection = db.getCollection("test"); + assertNotNull(testCollection); + long prevSize = testCollection.find().size(); + + db.close(); + + db = null; + + db = TestUtil.createDb(fileName, "test-user", "test-password"); + + assertNotNull(db); + testCollection = db.getCollection("test"); + assertNotNull(testCollection); + long sizeNow = testCollection.find().size(); + assertEquals(prevSize, sizeNow); + + db.close(); + db = null; + db = TestUtil.createDb(fileName, "test-user", "test-password"); + + testCollection = db.getCollection("test"); + testCollection.insert(createDocument("firstName", "fn12") + .put("lastName", "ln12") + .put("birthDay", simpleDateFormat.parse("2010-07-01T16:02:48.440Z")) + .put("data", new byte[]{10, 20, 30}) + .put("body", "a quick brown fox jump over the lazy dog")); + + db.close(); + db = null; + db = TestUtil.createDb(fileName, "test-user", "test-password"); + + testCollection = db.getCollection("test"); + assertNotNull(testCollection); + sizeNow = testCollection.find().size(); + assertEquals(prevSize + 1, sizeNow); + } + + @Test + public void testClose() { + NitriteCollection testCollection = db.getCollection("test"); + testCollection.insert(createDocument("a", "b")); + db.close(); + + assertFalse(testCollection.isOpen()); + } + + @Test + public void testGetCollection() { + NitriteCollection collection = db.getCollection("test-collection"); + assertNotNull(collection); + assertEquals(collection.getName(), "test-collection"); + } + + @Test + public void testGetRepository() { + ObjectRepository repository = db.getRepository(NitriteTest.class); + assertNotNull(repository); + assertEquals(repository.getType(), NitriteTest.class); + } + + @Test + public void testGetRepositoryWithKey() { + ObjectRepository repository = db.getRepository(NitriteTest.class, "key"); + assertNotNull(repository); + assertEquals(repository.getType(), NitriteTest.class); + assertFalse(db.hasRepository(NitriteTest.class)); + assertTrue(db.hasRepository(NitriteTest.class, "key")); + } + + @Test + public void testMultipleGetCollection() { + NitriteCollection collection = db.getCollection("test-collection"); + assertNotNull(collection); + assertEquals(collection.getName(), "test-collection"); + + NitriteCollection collection2 = db.getCollection("test-collection"); + assertNotNull(collection2); + assertEquals(collection2.getName(), "test-collection"); + } + + @Test + public void testMultipleGetRepository() { + ObjectRepository repository = db.getRepository(NitriteTest.class); + assertNotNull(repository); + assertEquals(repository.getType(), NitriteTest.class); + + ObjectRepository repository2 = db.getRepository(NitriteTest.class); + assertNotNull(repository2); + assertEquals(repository2.getType(), NitriteTest.class); + } + + @Test(expected = ValidationException.class) + public void testGetRepositoryInvalid() { + db.getRepository(null); + } + + @Test(expected = NitriteIOException.class) + public void testGetCollectionNullStore() { + db = Nitrite.builder().openOrCreate(); + db.close(); + db.getCollection("test"); + } + + @Test(expected = NitriteIOException.class) + public void testGetRepositoryNullStore() { + db = Nitrite.builder().openOrCreate(); + db.close(); + db.getRepository(NitriteTest.class); + } + + @Test(expected = NitriteIOException.class) + public void testGetKeyedRepositoryNullStore() { + db = Nitrite.builder().openOrCreate(); + db.close(); + db.getRepository(NitriteTest.class, "key"); + } + + @Test(expected = NitriteIOException.class) + public void testCommitNullStore() { + db = Nitrite.builder().openOrCreate(); + db.close(); + db.commit(); + } + + @Test(expected = ValidationException.class) + public void testGetCollectionInvalidName() { + db.getCollection(META_MAP_NAME); + } + + @Test + public void testIssue185() throws InterruptedException { + final ObjectRepository repository = db.getRepository(Receipt.class); + final Receipt receipt = new Receipt(); + receipt.clientRef = "111-11111"; + receipt.status = Receipt.Status.PREPARING; + CountDownLatch latch = new CountDownLatch(1); + + new Thread(() -> { + for (int i = 0; i < 1000; ++i) { + try { + repository.update(receipt, true); + try { + Thread.sleep(50); + } catch (InterruptedException ignored) { + } + repository.remove(receipt); + try { + Thread.sleep(50); + } catch (InterruptedException ignored) { + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + latch.countDown(); + }).start(); + + for (int i = 0; i < 1000; ++i) { + repository.find(where("status").eq(Receipt.Status.COMPLETED).not(), + FindOptions.orderBy("createdTimestamp", SortOrder.Descending)).toList(); + try { + Thread.sleep(50); + } catch (InterruptedException ignored) { + } + } + latch.await(); + } + + @Test + public void testIssue193() throws InterruptedException { + final ObjectRepository repository = db.getRepository(Receipt.class); + final PodamFactory factory = new PodamFactoryImpl(); + final String[] refs = new String[]{"1", "2", "3", "4", "5"}; + final Random random = new Random(); + ExecutorService pool = ThreadPoolManager.workerPool(); + + final CountDownLatch latch = new CountDownLatch(10000); + for (int i = 0; i < 10000; i++) { + pool.submit(() -> { + int refIndex = random.nextInt(5); + Receipt receipt = factory.manufacturePojoWithFullData(Receipt.class); + receipt.setClientRef(refs[refIndex]); + repository.update(receipt, true); + latch.countDown(); + }); + } + + latch.await(); + assertTrue(repository.find().size() <= 5); + pool.shutdown(); + } + + @Test + public void testIssue212() { + NitriteCollection collection = db.getCollection("testIssue212"); + Document doc1 = createDocument("key", "key").put("second_key", "second_key").put("third_key", "third_key"); + Document doc2 = createDocument("key", "key").put("second_key", "second_key").put("fourth_key", "fourth_key"); + Document doc = createDocument("fifth_key", "fifth_key"); + + if (!collection.hasIndex("key")) { + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "key"); + } + if (!collection.hasIndex("second_key")) { + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "second_key"); + } + + collection.insert(doc1, doc2); + collection.update(where("key").eq("key").and(where("second_key").eq("second_key")), + doc, UpdateOptions.updateOptions(true)); + + for (Document document : collection.find()) { + System.out.println(document); + } + } + + @Test + public void testIssue245() throws Exception { + class ThreadRunner implements Runnable { + @Override + public void run() { + try { + long id = Thread.currentThread().getId(); + NitriteCollection collection = db.getCollection("testIssue245"); + + for (int i = 0; i < 5; i++) { + + System.out.println("Thread ID = " + id + " Inserting doc " + i); + Document doc = Document.createDocument(UUID.randomUUID().toString(), UUID.randomUUID().toString()); + + WriteResult result = collection.insert(doc);//db.commit(); + System.out.println("Result of insert = " + result.getAffectedCount()); + System.out.println("Thread id = " + id + " --> count = " + collection.size()); + + Thread.sleep(10); + + }//for closing + + collection.close(); + + } catch (Throwable e) { + e.printStackTrace(); + } + } + }; + + Thread t0 = new Thread(new ThreadRunner()); + Thread t1 = new Thread(new ThreadRunner()); + Thread t2 = new Thread(new ThreadRunner()); + + t0.start(); + t1.start(); + t2.start(); + + Thread.sleep(10 * 1000); + + t0.join(); + t1.join(); + t2.join(); + + NitriteCollection collection = db.getCollection("testIssue245"); + System.out.println("No of Documents = " + collection.size()); + collection.close(); + db.close(); + } + + @Data + @AllArgsConstructor + @NoArgsConstructor + public static class CompatChild implements Mappable { + private Long childId; + private String lastName; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("childId", childId) + .put("lastName", lastName); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + childId = document.get("childId", Long.class); + lastName = document.get("lastName", String.class); + } + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Indices({ + @Index(value = "synced", type = IndexType.NON_UNIQUE) + }) + public static class Receipt implements Mappable { + @Id + private String clientRef; + private Boolean synced; + private Status status; + private Long createdTimestamp = System.currentTimeMillis(); + + @Override + public Document write(NitriteMapper mapper) { + return createDocument("status", status) + .put("clientRef", clientRef) + .put("synced", synced) + .put("createdTimestamp", createdTimestamp); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + if (document != null) { + Object status = document.get("status"); + if (status instanceof Status) { + this.status = (Status) status; + } else { + this.status = Status.valueOf(status.toString()); + } + this.clientRef = document.get("clientRef", String.class); + this.synced = document.get("synced", Boolean.class); + this.createdTimestamp = document.get("createdTimestamp", Long.class); + } + } + + public enum Status { + COMPLETED, + PREPARING, + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/CustomFilterTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/CustomFilterTest.java new file mode 100644 index 000000000..75a15f156 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/CustomFilterTest.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.dizitart.no2.integration.collection.BaseCollectionTest; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee. + */ +public class CustomFilterTest extends BaseCollectionTest { + + @Test + public void testCustomFilter() { + insert(); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "firstName"); + DocumentCursor cursor = collection.find(element -> element.getSecond().get("firstName", String.class) + .equalsIgnoreCase("FN1")); + + assertEquals(cursor.size(), 1); + assertEquals(cursor.firstOrNull().get("firstName"), "fn1"); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/DbWriteCloseReadTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/DbWriteCloseReadTest.java new file mode 100644 index 000000000..ccf825dfe --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/DbWriteCloseReadTest.java @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.index.IndexType; +import org.junit.Rule; +import org.junit.Test; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.collection.FindOptions.orderBy; +import static org.dizitart.no2.filters.Filter.*; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class DbWriteCloseReadTest { + private final String fileName = TestUtil.getRandomTempDbFile(); + private Nitrite db; + private volatile boolean writeCompleted = false; + + @Rule + public Retry retry = new Retry(3); + + @Test + public void testWriteCloseRead() throws Exception { + try { + createDb(); + writeCollection(); + writeIndex(); + insertInCollection(); + } catch (ParseException pe) { + // ignore + } finally { + writeCompleted = true; + } + + try { + assertTrue(writeCompleted); + readCollection(); + } catch (Exception e) { + fail("collection read failed - " + e.getMessage()); + } finally { + deleteDb(); + } + } + + void createDb() { + db = TestUtil.createDb(fileName); + db.close(); + } + + void writeCollection() { + NitriteCollection collection; + + db = TestUtil.createDb(fileName); + + collection = db.getCollection("test"); + collection.remove(ALL); + db.close(); + } + + void writeIndex() { + NitriteCollection collection; + + db = TestUtil.createDb(fileName); + + collection = db.getCollection("test"); + collection.remove(ALL); + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + collection.createIndex("firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + db.close(); + } + + void insertInCollection() throws Exception { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); + + Document doc1 = createDocument("firstName", "fn1") + .put("lastName", "ln1") + .put("birthDay", simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + .put("data", new byte[]{1, 2, 3}) + .put("body", "a quick brown fox jump over the lazy dog"); + Document doc2 = createDocument("firstName", "fn2") + .put("lastName", "ln2") + .put("birthDay", simpleDateFormat.parse("2010-06-12T16:02:48.440Z")) + .put("data", new byte[]{3, 4, 3}) + .put("body", "quick hello world from nitrite"); + Document doc3 = createDocument("firstName", "fn3") + .put("lastName", "ln2") + .put("birthDay", simpleDateFormat.parse("2014-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + + NitriteCollection collection; + + db = TestUtil.createDb(fileName); + + collection = db.getCollection("test"); + + WriteResult result = collection.insert(doc1, doc2, doc3); + assertEquals(result.getAffectedCount(), 3); + + db.commit(); + db.close(); + } + + void readCollection() throws Exception { + NitriteCollection collection; + + db = TestUtil.createDb(fileName); + + collection = db.getCollection("test"); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").gt(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").gte(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lt(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").lte(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lte(new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").lt(new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").gt(new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("birthDay").gte(new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("birthDay").lte(new Date()).and(where("firstName").eq("fn1"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").lte(new Date()).or(where("firstName").eq("fn12"))); + assertEquals(cursor.size(), 3); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + )); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + ).not()); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").eq((byte) 4)); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").lt(4)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("firstName").notIn("fn1", "fn2")); + assertEquals(cursor.size(), 1); + + collection.createIndex("birthDay"); + cursor = collection.find(orderBy("birthDay", SortOrder.Descending).skip(1).limit(2)); + assertEquals(cursor.size(), 2); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(TestUtil.isSorted(dateList, false)); + + cursor = collection.find(where("body").text("Lorem")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("body").text("quick")); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("body").text("nosql")); + assertEquals(cursor.size(), 0); + + db.close(); + } + + void deleteDb() { + if (db != null && !db.isClosed()) { + db.close(); + } + TestUtil.deleteDb(fileName); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/DocumentMetadataTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/DocumentMetadataTest.java new file mode 100644 index 000000000..15d01451f --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/DocumentMetadataTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.dizitart.no2.integration.collection.BaseCollectionTest; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.events.EventType; +import org.junit.Test; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee. + */ +public class DocumentMetadataTest extends BaseCollectionTest { + @Test + public void testTimeStamp() { + Document document = createDocument("test_key", "test_value"); + assertEquals(document.getRevision().intValue(), 0); + assertEquals(document.getLastModifiedSinceEpoch().longValue(), 0L); + + collection.insert(document); + document = collection.find().firstOrNull(); + + assertEquals(document.getRevision().intValue(), 1); + assertTrue(document.getLastModifiedSinceEpoch() > 0); + + long previous = document.getRevision(); + + DocumentCursor cursor = collection.find(where("test_key").eq("test_value")); + document = cursor.firstOrNull(); + document.put("another_key", "another_value"); + + collection.update(document); + cursor = collection.find(where("test_key").eq("test_value")); + document = cursor.firstOrNull(); + + assertTrue(document.getRevision() > previous); + + final long time = document.getRevision(); + final Document removed = document; + + collection.subscribe(changeInfo -> { + if (changeInfo.getEventType() == EventType.Remove) { + assertTrue(removed.getRevision() > time); + } + }); + + collection.remove(document); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/MultiThreadedTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/MultiThreadedTest.java new file mode 100644 index 000000000..16dc19ca3 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/MultiThreadedTest.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.concurrent.ThreadPoolManager; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.util.Date; +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + + +/** + * @author Anindya Chatterjee. + */ +public class MultiThreadedTest { + private static final String fileName = TestUtil.getRandomTempDbFile(); + private NitriteCollection collection; + private final int threadCount = 20; + private final CountDownLatch latch = new CountDownLatch(threadCount); + private final int iterationCount = 100; + private final Random generator = new Random(); + private final AtomicInteger docCounter = new AtomicInteger(0); + private ExecutorService executor; + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + executor = ThreadPoolManager.getThreadPool(threadCount, "MultiThreadedTest"); + } + + @Test + public void testOperations() throws InterruptedException { + db = TestUtil.createDb(fileName); + collection = db.getCollection("test"); + collection.remove(Filter.ALL); + collection.createIndex("unixTime"); + db.commit(); + + for (int i = 0; i < threadCount; i++) { + executor.submit(() -> { + for (int j = 0; j < iterationCount; j++) { + try { + Document document = generate(); + collection.insert(document); + + if (j == iterationCount / 2 + && !collection.hasIndex("text") + && !collection.hasIndex("date")) { + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "text"); + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "date"); + } + + long unixTime = (long) document.get("unixTime"); + DocumentCursor cursor = collection.find(where("unixTime").eq(unixTime)); + assertTrue(cursor.size() >= 0); + + if (collection.hasIndex("text") && !collection.isIndexing("text")) { + String textData = (String) document.get("text"); + cursor = collection.find(where("text").text(textData)); + assertTrue(cursor.size() >= 0); + } + + assertTrue(collection.hasIndex("unixTime")); + } catch (Throwable e) { + System.out.println("Exception at thread " + + Thread.currentThread().getName() + " with iteration " + j); + e.printStackTrace(); + } + } + latch.countDown(); + }); + } + + latch.await(); + + db.commit(); + + assertTrue(collection.hasIndex("text")); + assertTrue(collection.hasIndex("date")); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), docCounter.get()); + + cursor = collection.find(where("unixTime").gt(1L)); + assertEquals(cursor.size(), docCounter.get()); + + db.close(); + } + + @After + public void cleanUp() { + if (db != null && !db.isClosed()) { + db.close(); + } + TestUtil.deleteDb(fileName); + + if (executor != null && !executor.isShutdown()) { + executor.shutdown(); + executor = null; + } + } + + private synchronized Document generate() { + Document document = createDocument("unixTime", System.nanoTime() + docCounter.incrementAndGet()); + byte[] blob = new byte[1024]; + generator.nextBytes(blob); + document.put("blob", blob); + document.put("text", UUID.randomUUID().toString().replaceAll("-", " ")); + document.put("date", new Date()); + return document; + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/NitriteBuilderNegativeTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/NitriteBuilderNegativeTest.java new file mode 100644 index 000000000..9bd402c29 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/NitriteBuilderNegativeTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.exceptions.NitriteIOException; +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; + +import static org.dizitart.no2.integration.TestUtil.*; + + +/** + * @author Anindya Chatterjee. + */ +public class NitriteBuilderNegativeTest { + private final String filePath = getRandomTempDbFile(); + private Nitrite db1, db2; + + @Rule + public Retry retry = new Retry(3); + + @Test(expected = NitriteIOException.class) + public void testOpenWithLock() { + db1 = createDb(filePath); + db2 = createDb(filePath); + } + + @Test(expected = NitriteIOException.class) + public void testInvalidDirectory() { + String filePath = "/ytgr/hfurh/frij.db"; + db1 = createDb(filePath); + } + + @After + public void cleanUp() { + if (db1 != null && !db1.isClosed()) { + db1.close(); + } + + if (db2 != null && !db2.isClosed()) { + db2.close(); + } + deleteDb(filePath); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/NitriteBuilderTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/NitriteBuilderTest.java new file mode 100644 index 000000000..f6436ee6d --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/NitriteBuilderTest.java @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.apache.commons.io.FileUtils; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteBuilder; +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.FieldValues; +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.dizitart.no2.exceptions.NitriteIOException; +import org.dizitart.no2.exceptions.NitriteSecurityException; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.NitriteIndexer; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Index; +import org.dizitart.no2.rocksdb.RocksDBConfig; +import org.dizitart.no2.rocksdb.RocksDBModule; +import org.dizitart.no2.store.StoreConfig; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.LinkedHashSet; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.common.module.NitriteModule.module; +import static org.dizitart.no2.common.util.StringUtils.isNullOrEmpty; +import static org.dizitart.no2.integration.TestUtil.createDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class NitriteBuilderTest { + private String fakeFile; + private String filePath; + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void startup() { + fakeFile = getRandomTempDbFile(); + filePath = getRandomTempDbFile(); + } + + @After + public void cleanup() { + (new NitriteConfig()).fieldSeparator("."); + + if (db != null && !db.isClosed()) { + db.close(); + } + + if (Files.exists(Paths.get(filePath))) { + TestUtil.deleteDb(filePath); + } + + if (Files.exists(Paths.get(fakeFile))) { + TestUtil.deleteDb(fakeFile); + } + } + + @Test + public void testConfig() { + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(filePath) + .build(); + + NitriteBuilder nitriteBuilder = Nitrite.builder(); + nitriteBuilder.loadModule(module(new CustomIndexer())); + nitriteBuilder.loadModule(storeModule); + + db = nitriteBuilder.openOrCreate(); + NitriteConfig config = nitriteBuilder.getNitriteConfig(); + RocksDBConfig storeConfig = (RocksDBConfig) db.getStore().getStoreConfig(); + + assertEquals(config.findIndexer("Custom").getClass(), CustomIndexer.class); + assertFalse(storeConfig.isReadOnly()); + assertFalse(storeConfig.isInMemory()); + assertFalse(isNullOrEmpty(storeConfig.filePath())); + + db.close(); + TestUtil.deleteDb(filePath); + } + + @Test + public void testConfigWithFile() throws IOException { + File file = new File(filePath); + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(file) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .openOrCreate(); + StoreConfig storeConfig = db.getStore().getStoreConfig(); + + assertFalse(storeConfig.isInMemory()); + assertFalse(isNullOrEmpty(storeConfig.filePath())); + + NitriteCollection test = db.getCollection("test"); + assertNotNull(test); + + db.commit(); + db.close(); + + FileUtils.deleteDirectory(file.getAbsoluteFile()); + } + + @Test(expected = InvalidOperationException.class) + public void testConfigWithFileNull() { + File file = null; + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(file) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .openOrCreate(); + StoreConfig storeConfig = db.getStore().getStoreConfig(); + + assertTrue(storeConfig.isInMemory()); + assertTrue(isNullOrEmpty(storeConfig.filePath())); + + NitriteCollection test = db.getCollection("test"); + assertNotNull(test); + + db.commit(); + db.close(); + } + + @Test + public void testPopulateRepositories() { + File file = new File(filePath); + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(file) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .openOrCreate(); + + NitriteCollection collection = db.getCollection("test"); + collection.insert(createDocument("id1", "value")); + + ObjectRepository repository = db.getRepository(TestObject.class); + repository.insert(new TestObject("test", 1L)); + + ObjectRepository repository2 = db.getRepository(TestObject.class, "key"); + TestObject object = new TestObject(); + object.stringValue = "test2"; + object.longValue = 2L; + repository2.insert(object); + + ObjectRepository repository3 = db.getRepository(TestObject2.class, "key"); + TestObject2 object2 = new TestObject2(); + object2.stringValue = "test2"; + object2.longValue = 2L; + repository3.insert(object2); + + db.commit(); + db.close(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .openOrCreate(); + assertTrue(db.hasCollection("test")); + assertTrue(db.hasRepository(TestObject.class)); + assertTrue(db.hasRepository(TestObject.class, "key")); + assertFalse(db.hasRepository(TestObject2.class)); + assertTrue(db.hasRepository(TestObject2.class, "key")); + } + + + @Test + public void testNitriteMapper() { + NitriteBuilder builder = Nitrite.builder(); + builder.loadModule(module(new CustomNitriteMapper())); + NitriteConfig config = builder.getNitriteConfig(); + assertNotNull(config.nitriteMapper()); + } + + @Test(expected = NitriteSecurityException.class) + public void testOpenOrCreateNullUserId() { + NitriteBuilder builder = Nitrite.builder(); + builder.openOrCreate(null, "abcd"); + } + + @Test(expected = NitriteSecurityException.class) + public void testOpenOrCreateNullPassword() { + NitriteBuilder builder = Nitrite.builder(); + builder.openOrCreate("abcd", null); + } + + + @Test(expected = NitriteIOException.class) + public void testDbInvalidDirectory() { + fakeFile = System.getProperty("java.io.tmpdir") + File.separator + "fake" + File.separator + "fake.db"; + db = createDb(fakeFile, "test", "test"); + assertNull(db); + } + + @Test + public void testFieldSeparator() { + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(filePath) + .build(); + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator("::") + .openOrCreate(); + + Document document = createDocument("firstName", "John") + .put("colorCodes", new Document[]{createDocument("color", "Red"), createDocument("color", "Green")}) + .put("address", createDocument("street", "ABCD Road")); + + String street = document.get("address::street", String.class); + assertEquals("ABCD Road", street); + + // use default separator, it should return null + street = document.get("address.street", String.class); + assertNull(street); + + assertEquals(document.get("colorCodes::1::color"), "Green"); + } + + private static class CustomIndexer implements NitriteIndexer { + + @Override + public String getIndexType() { + return "Custom"; + } + + @Override + public void validateIndex(Fields fields) { + + } + + @Override + public void dropIndex(IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig) { + + } + + @Override + public void writeIndexEntry(FieldValues fieldValues, IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig) { + + } + + @Override + public void removeIndexEntry(FieldValues fieldValues, IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig) { + + } + + @Override + public LinkedHashSet findByFilter(FindPlan findPlan, NitriteConfig nitriteConfig) { + return null; + } + + @Override + public void initialize(NitriteConfig nitriteConfig) { + + } + } + + public static class CustomNitriteMapper implements NitriteMapper { + + @Override + public Target convert(Source source, Class type) { + return null; + } + + @Override + public boolean isValueType(Class type) { + return false; + } + + @Override + public boolean isValue(Object object) { + return false; + } + + @Override + public void initialize(NitriteConfig nitriteConfig) { + + } + } + + @Index(value = "longValue") + private static class TestObject implements Mappable { + private String stringValue; + private Long longValue; + + public TestObject() { + } + + public TestObject(String stringValue, Long longValue) { + this.longValue = longValue; + this.stringValue = stringValue; + } + + @Override + public Document write(NitriteMapper mapper) { + return createDocument("stringValue", stringValue) + .put("longValue", longValue); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + if (document != null) { + this.stringValue = document.get("stringValue", String.class); + this.longValue = document.get("longValue", Long.class); + } + } + } + + @Index(value = "longValue") + private static class TestObject2 implements Mappable { + private String stringValue; + private Long longValue; + + public TestObject2() { + } + + public TestObject2(String stringValue, Long longValue) { + this.longValue = longValue; + this.stringValue = stringValue; + } + + @Override + public Document write(NitriteMapper mapper) { + return createDocument("stringValue", stringValue) + .put("longValue", longValue); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + if (document != null) { + this.stringValue = document.get("stringValue", String.class); + this.longValue = document.get("longValue", Long.class); + } + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/NitriteCorruptedTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/NitriteCorruptedTest.java new file mode 100644 index 000000000..72e18a326 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/NitriteCorruptedTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.concurrent.ThreadPoolManager; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.util.concurrent.ExecutorService; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.Filter.ALL; +import static org.dizitart.no2.integration.TestUtil.createDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee + */ +public class NitriteCorruptedTest { + private Nitrite db; + private NitriteCollection collection; + private final String fileName = getRandomTempDbFile(); + private Thread thread; + private final ExecutorService dbPool = ThreadPoolManager.getThreadPool(Runtime.getRuntime().availableProcessors(), + "NitriteCorruptedTest"); + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + db = createDb(fileName); + + collection = db.getCollection("test"); + collection.remove(ALL); + + thread = new Thread(() -> { + for (int i = 0; i < 50000; i++) { + + // Interruption Guard + if (Thread.interrupted()) { + break; + } + + Document doc1 = createDocument(String.valueOf(System.currentTimeMillis()), "fn1") + .put("lastName", "ln1") + .put("data", new byte[]{1, 2, 3}) + .put("body", "a quick brown fox jump over the lazy dog"); + + // Separate user thread from Db write thread + dbPool.submit(() -> collection.insert(doc1)); + } + }); + } + + @After + public void tearDown() throws Exception { + if (collection.isOpen()) { + collection.remove(ALL); + collection.close(); + } + if (db != null && !db.isClosed()) { + db.close(); + } + TestUtil.deleteDb(fileName); + } + + @Test(timeout = 10000) + public void issue118() throws InterruptedException { + try { + thread.start(); + Thread.sleep(10); + thread.interrupt(); + Thread.sleep(500); + assertTrue(collection.isOpen()); + assertFalse(db.isClosed()); + } catch (InterruptedException e) { + if (db != null && !db.isClosed()) { + db.close(); + } + throw e; + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/NitriteSecurityNegativeTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/NitriteSecurityNegativeTest.java new file mode 100644 index 000000000..222038b62 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/NitriteSecurityNegativeTest.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.apache.commons.io.FileUtils; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.exceptions.NitriteException; +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; + +import java.io.File; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.integration.TestUtil.createDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee. + */ +public class NitriteSecurityNegativeTest { + private Nitrite db; + private final String fileName = getRandomTempDbFile(); + + @Rule + public Retry retry = new Retry(3); + + @Test(expected = NitriteException.class) + public void testOpenSecuredWithoutCredential() { + db = createDb(fileName, "test-user", "test-password"); + NitriteCollection dbCollection = db.getCollection("test"); + dbCollection.insert(createDocument("test", "test")); + db.commit(); + db.close(); + + db = createDb(fileName); + dbCollection = db.getCollection("test"); + assertEquals(dbCollection.find().size(), 1); + } + + @Test(expected = NitriteException.class) + public void testOpenUnsecuredWithCredential() { + db = createDb(fileName); + NitriteCollection dbCollection = db.getCollection("test"); + dbCollection.insert(createDocument("test", "test")); + db.commit(); + db.close(); + + db = createDb(fileName, "test-user", "test-password"); + dbCollection = db.getCollection("test"); + assertEquals(dbCollection.find().size(), 1); + } + + @Test(expected = NitriteException.class) + public void testWrongCredential() { + db = createDb(fileName, "test-user", "test-password"); + NitriteCollection dbCollection = db.getCollection("test"); + dbCollection.insert(createDocument("test", "test")); + db.commit(); + db.close(); + + db = createDb(fileName, "test-user", "test-password2"); + dbCollection = db.getCollection("test"); + assertEquals(dbCollection.find().size(), 1); + } + + @After + public void cleanUp() { + if (db != null && !db.isClosed()) { + db.close(); + } + + FileUtils.deleteQuietly(new File(fileName)); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/NitriteSecurityTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/NitriteSecurityTest.java new file mode 100644 index 000000000..ec9663db3 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/NitriteSecurityTest.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.apache.commons.io.FileUtils; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.exceptions.NitriteSecurityException; +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; + +import java.io.File; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.integration.TestUtil.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * @author Anindya Chatterjee. + */ +public class NitriteSecurityTest { + private Nitrite db; + private final String fileName = getRandomTempDbFile(); + + @Rule + public Retry retry = new Retry(3); + + @Test + public void testSecured() { + db = createDb(fileName, "test-user", "test-password"); + NitriteCollection dbCollection = db.getCollection("test"); + dbCollection.insert(createDocument("test", "test")); + db.commit(); + db.close(); + + db = createDb(fileName, "test-user", "test-password"); + dbCollection = db.getCollection("test"); + assertEquals(dbCollection.find().size(), 1); + db.close(); + deleteDb(fileName); + } + + @Test + public void testUnsecured() { + db = createDb(fileName); + NitriteCollection dbCollection = db.getCollection("test"); + dbCollection.insert(createDocument("test", "test")); + db.commit(); + db.close(); + + db = createDb(fileName); + dbCollection = db.getCollection("test"); + assertEquals(dbCollection.find().size(), 1); + db.close(); + deleteDb(fileName); + } + + @Test + public void testIssue116() { + db = createDb(fileName, "test-user", "test-password"); + db.close(); + try { + db = createDb(fileName,"test-user2", "test-password2"); + } catch (NitriteSecurityException se) { + db = createDb(fileName,"test-user", "test-password"); + assertNotNull(db); + } finally { + db.close(); + deleteDb(fileName); + } + } + + @After + public void cleanUp() { + if (db != null && !db.isClosed()) { + db.close(); + } + + FileUtils.deleteQuietly(new File(fileName)); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/NitriteStressTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/NitriteStressTest.java new file mode 100644 index 000000000..90b15b3a1 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/NitriteStressTest.java @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import lombok.Data; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; +import org.dizitart.no2.repository.annotations.Indices; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import uk.co.jemos.podam.api.PodamFactory; +import uk.co.jemos.podam.api.PodamFactoryImpl; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.atomic.AtomicLong; + +import static org.dizitart.no2.integration.TestUtil.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + + +/** + * @author Anindya Chatterjee + */ +public class NitriteStressTest { + private static final int TEST_SET_COUNT = 15000; + private final PodamFactory podamFactory = new PodamFactoryImpl(); + private final String fileName = getRandomTempDbFile(); + private Nitrite db; + private NitriteCollection collection; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void before() { + db = createDb(fileName); + collection = db.getCollection("test"); + System.out.println(fileName); + } + + @After + public void cleanUp() { + if (db != null && !db.isClosed()) { + long start = System.currentTimeMillis(); + db.close(); + System.out.println("Time to compact and close - " + (System.currentTimeMillis() - start) / 1000 + " seconds"); + } + + deleteDb(fileName); + } + + @Test + public void stressTest() { + ObjectRepository testRepository = db.getRepository(TestDto.class); + testRepository.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "lastName"); + testRepository.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "birthDate"); + + int counter = 0; + try { + for (TestDto testDto : createTestSet()) { + testRepository.insert(testDto); + counter++; + } + } catch (Throwable t) { + System.err.println("Crashed after " + counter + " records"); + throw t; + } + + int size = testRepository.find().toList().size(); + assertEquals(counter, size); + } + + @Test + public void testIssue41() { + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "number"); + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "name"); + collection.createIndex("counter"); + + Random random = new Random(); + AtomicLong counter = new AtomicLong(System.currentTimeMillis()); + PodamFactory factory = new PodamFactoryImpl(); + + long start = System.currentTimeMillis(); + for (int i = 0; i < 100000; i++) { + Document doc = Document.createDocument(); + doc.put("number", random.nextDouble()); + doc.put("name", factory.manufacturePojo(String.class)); + doc.put("counter", counter.getAndIncrement()); + collection.insert(doc); + if (i % 10000 == 0) { + System.out.println(i + " entries written"); + } + } + System.out.println("Records inserted in " + ((System.currentTimeMillis() - start) / (1000 * 60)) + " minutes"); + + if (db.hasUnsavedChanges()) { + db.commit(); + } + + start = System.currentTimeMillis(); + DocumentCursor cursor = collection.find(); + System.out.println("Size ->" + cursor.size()); + System.out.println("Records size calculated in " + ((System.currentTimeMillis() - start) / (1000)) + " seconds"); + + int i = 0; + start = System.currentTimeMillis(); + for (Document element : cursor) { + assertNotNull(element); + i++; + if (i % 10000 == 0) { + System.out.println(i + " entries processed"); + } + } + System.out.println("Iteration completed in " + ((System.currentTimeMillis() - start) / (1000)) + " seconds"); + } + + @Test + public void testRepoPerformanceWithIndex() { + // warm-up + List items = getItems(PerfTestIndexed.class); + ObjectRepository repo = db.getRepository(PerfTestIndexed.class); + for (PerfTestIndexed item : items) { + assertNotNull(item); + repo.insert(item); + } + repo.remove(Filter.ALL); + repo.drop(); + + // actual calculation + repo = db.getRepository(PerfTestIndexed.class); + long start = System.currentTimeMillis(); + for (PerfTestIndexed item : items) { + repo.insert(item); + } + long diff = System.currentTimeMillis() - start; + System.out.println("Time take to insert 10000 indexed items - " + diff + "ms"); + + start = System.currentTimeMillis(); + repo.remove(Filter.ALL); + diff = System.currentTimeMillis() - start; + System.out.println("Time take to remove 10000 indexed items - " + diff + "ms"); + } + + @Test + public void testRepoPerformanceWithoutIndex() { + // warm-up + List items = getItems(PerfTest.class); + ObjectRepository repo = db.getRepository(PerfTest.class); + for (PerfTest item : items) { + assertNotNull(item); + repo.insert(item); + } + repo.remove(Filter.ALL); + repo.drop(); + + // actual calculation + repo = db.getRepository(PerfTest.class); + long start = System.currentTimeMillis(); + for (PerfTest item : items) { + repo.insert(item); + } + long diff = System.currentTimeMillis() - start; + System.out.println("Time take to insert 10000 non-indexed items - " + diff + "ms"); + + start = System.currentTimeMillis(); + repo.remove(Filter.ALL); + diff = System.currentTimeMillis() - start; + System.out.println("Time take to remove 10000 non-indexed items - " + diff + "ms"); + } + + private List createTestSet() { + List testData = new ArrayList<>(); + for (int i = 0; i < TEST_SET_COUNT; i++) { + TestDto testRecords = podamFactory.manufacturePojo(TestDto.class); + testData.add(testRecords); + } + return testData; + } + + private List getItems(Class type) { + PodamFactory generator = new PodamFactoryImpl(); + List items = new ArrayList<>(); + for (int i = 0; i < 10000; i++) { + items.add(generator.manufacturePojoWithFullData(type)); + } + assertEquals(items.size(), 10000); + return items; + } + + @Data + public static class TestDto implements Mappable { + + @XmlElement( + name = "StudentNumber", + required = true + ) + @Id + protected String studentNumber; + + @XmlElement( + name = "LastName", + required = true + ) + protected String lastName; + + @XmlElement( + name = "Prefixes" + ) + protected String prefixes; + + @XmlElement( + name = "Initials", + required = true + ) + protected String initials; + + @XmlElement( + name = "FirstNames" + ) + protected String firstNames; + @XmlElement( + name = "Nickname" + ) + protected String nickName; + + @XmlElement( + name = "BirthDate", + required = true + ) + @XmlSchemaType( + name = "date" + ) + protected String birthDate; + + + public TestDto() { + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("studentNumber", studentNumber) + .put("lastName", lastName) + .put("prefixes", prefixes) + .put("initials", initials) + .put("firstNames", firstNames) + .put("nickName", nickName) + .put("birthDate", birthDate); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + studentNumber = document.get("studentNumber", String.class); + lastName = document.get("lastName", String.class); + prefixes = document.get("prefixes", String.class); + initials = document.get("initials", String.class); + firstNames = document.get("firstNames", String.class); + nickName = document.get("nickName", String.class); + birthDate = document.get("birthDate", String.class); + } + } + + @Data + public static class PerfTest implements Mappable { + private String firstName; + private String lastName; + private Integer age; + private String text; + + @Override + public Document write(NitriteMapper mapper) { + Document document = Document.createDocument(); + document.put("firstName", firstName); + document.put("lastName", lastName); + document.put("age", age); + document.put("text", text); + return document; + } + + @Override + public void read(NitriteMapper mapper, Document document) { + this.firstName = (String) document.get("firstName"); + this.lastName = (String) document.get("lastName"); + this.age = (Integer) document.get("age"); + this.text = (String) document.get("text"); + } + } + + @Indices({ + @Index(value = "firstName", type = IndexType.NON_UNIQUE), + @Index(value = "age", type = IndexType.NON_UNIQUE), + @Index(value = "text", type = IndexType.FULL_TEXT), + }) + private static class PerfTestIndexed extends PerfTest { + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/Retry.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/Retry.java new file mode 100644 index 000000000..3d6a27d11 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/Retry.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * @author Anindya Chatterjee + */ +public class Retry implements TestRule { + private final int retryCount; + + public Retry(int retryCount) { + this.retryCount = retryCount; + } + + public Statement apply(Statement base, Description description) { + return statement(base, description); + } + + private Statement statement(final Statement base, final Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + Throwable caughtThrowable = null; + + // implement retry logic here + for (int i = 0; i < retryCount; i++) { + try { + base.evaluate(); + return; + } catch (Throwable t) { + caughtThrowable = t; + System.err.println(description.getDisplayName() + ": run " + (i + 1) + " failed"); + } + } + System.err.println(description.getDisplayName() + ": giving up after " + retryCount + " failures"); + throw caughtThrowable; + } + }; + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/SerializabilityTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/SerializabilityTest.java new file mode 100644 index 000000000..09ca50080 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/SerializabilityTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import lombok.Data; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.exceptions.ValidationException; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.File; +import java.io.Serializable; + +/** + * @author Anindya Chatterjee + */ +public class SerializabilityTest { + private NitriteCollection collection; + private File dbFile; + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + dbFile = new File(TestUtil.getRandomTempDbFile()); + db = TestUtil.createDb(dbFile.getPath()); + collection = db.getCollection("test"); + } + + @After + public void tearDown() { + if (db != null && !db.isClosed()) { + db.close(); + } + + if (dbFile.exists()) { + TestUtil.deleteDb(dbFile.getPath()); + } + } + + @Test(expected = ValidationException.class) + public void testSerializabilityValidation() { + for (int i = 0; i < 5; i++) { + Document doc = Document.createDocument(); + doc.put("key", i); + doc.put("data", new NotSerializableClass(Integer.toString(i))); + collection.insert(doc); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("Write " + i + " completed"); + } + } + + @Test + public void testSerializablity() { + for (int i = 0; i < 5; i++) { + Document doc = Document.createDocument(); + doc.put("key", i); + doc.put("data", new SerializableClass(Integer.toString(i))); + collection.insert(doc); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("Write " + i + " completed"); + } + } + + @Data + public static class NotSerializableClass { + private String myId; + + public NotSerializableClass(String myId) { + this.myId = myId; + } + } + + @Data + public static class SerializableClass implements Serializable { + private String myId; + + public SerializableClass(String myId) { + this.myId = myId; + } + } +} + + diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/TestUtil.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/TestUtil.java new file mode 100644 index 000000000..91a4101ad --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/TestUtil.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.FileUtils; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.exceptions.ObjectMappingException; +import org.dizitart.no2.rocksdb.RocksDBModule; + +import java.io.File; +import java.io.IOException; +import java.util.*; + +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee + */ +@Slf4j +public class TestUtil { + + public static String getRandomTempDbFile() { + String dataDir = System.getProperty("java.io.tmpdir") + File.separator + "nitrite" + File.separator + "data"; + File file = new File(dataDir); + if (!file.exists()) { + assertTrue(file.mkdirs()); + } + return file.getPath() + File.separator + UUID.randomUUID() + ".db"; + } + + @SneakyThrows + public static void deleteDb(String fileName) { + File file = new File(fileName); + FileUtils.deleteDirectory(file); + } + + public static > boolean isSorted(Iterable iterable, boolean ascending) { + Iterator iterator = iterable.iterator(); + if (!iterator.hasNext()) { + return true; + } + T t = iterator.next(); + while (iterator.hasNext()) { + T t2 = iterator.next(); + if (ascending) { + if (t.compareTo(t2) > 0) { + return false; + } + } else { + if (t.compareTo(t2) < 0) { + return false; + } + } + t = t2; + } + return true; + } + + public static Nitrite createDb() { + RocksDBModule storeModule = RocksDBModule.withConfig() + .build(); + + return Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .openOrCreate(); + } + + public static Nitrite createDb(String user, String password) { + RocksDBModule storeModule = RocksDBModule.withConfig() + .build(); + + return Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .openOrCreate(user, password); + } + + public static Nitrite createDb(String filePath) { + return Nitrite.builder() + .loadModule(new RocksDBModule(filePath)) + .fieldSeparator(".") + .openOrCreate(); + } + + public static Nitrite createDb(String filePath, String user, String password) { + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(filePath) + .build(); + + return Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .openOrCreate(user, password); + } + + public static Document parse(String json) { + try { + ObjectMapper objectMapper = createObjectMapper(); + JsonNode node = objectMapper.readValue(json, JsonNode.class); + return loadDocument(node); + } catch (IOException e) { + log.error("Error while parsing json", e); + throw new ObjectMappingException("failed to parse json " + json); + } + } + + private static Document loadDocument(JsonNode node) { + Map objectMap = new LinkedHashMap<>(); + Iterator> fields = node.fields(); + while (fields.hasNext()) { + Map.Entry entry = fields.next(); + String name = entry.getKey(); + JsonNode value = entry.getValue(); + Object object = loadObject(value); + objectMap.put(name, object); + } + + return Document.createDocument(objectMap); + } + + private static Object loadObject(JsonNode node) { + if (node == null) + return null; + try { + switch (node.getNodeType()) { + case ARRAY: + return loadArray(node); + case BINARY: + return node.binaryValue(); + case BOOLEAN: + return node.booleanValue(); + case MISSING: + case NULL: + return null; + case NUMBER: + return node.numberValue(); + case OBJECT: + case POJO: + return loadDocument(node); + case STRING: + return node.textValue(); + } + } catch (IOException e) { + return null; + } + return null; + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private static List loadArray(JsonNode array) { + if (array.isArray()) { + List list = new ArrayList(); + Iterator iterator = array.elements(); + while (iterator.hasNext()) { + Object element = iterator.next(); + if (element instanceof JsonNode) { + list.add(loadObject((JsonNode) element)); + } else { + list.add(element); + } + } + return list; + } + return null; + } + + private static ObjectMapper createObjectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.setVisibility( + objectMapper.getSerializationConfig().getDefaultVisibilityChecker() + .withFieldVisibility(JsonAutoDetect.Visibility.ANY) + .withGetterVisibility(JsonAutoDetect.Visibility.NONE) + .withIsGetterVisibility(JsonAutoDetect.Visibility.NONE)); + objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); + objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); + objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + objectMapper.findAndRegisterModules(); + return objectMapper; + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/BaseCollectionTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/BaseCollectionTest.java new file mode 100644 index 000000000..c1a34e3b0 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/BaseCollectionTest.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.FileUtils; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.rocksdb.RocksDBModule; +import org.dizitart.no2.rocksdb.formatter.KryoObjectFormatter; +import org.dizitart.no2.rocksdb.serializers.JodaTimeKryoKeySerializer; +import org.joda.time.DateTime; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Collection; +import java.util.Locale; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.Filter.ALL; +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; + +@Slf4j +@RunWith(value = Parameterized.class) +public abstract class BaseCollectionTest { + @Parameterized.Parameter + public boolean isSecured = false; + + protected Nitrite db; + protected NitriteCollection collection; + protected Document doc1, doc2, doc3; + protected SimpleDateFormat simpleDateFormat; + private final String fileName = getRandomTempDbFile(); + protected final KryoObjectFormatter fstMarshaller = new KryoObjectFormatter(); + + @Rule + public Retry retry = new Retry(3); + + @Parameterized.Parameters(name = "Secured = {0}") + public static Collection data() { + return Arrays.asList(new Object[][]{ + {false}, + {true}, + }); + } + + @Before + public void setUp() { + try { + openDb(); + + simpleDateFormat + = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); + + doc1 = createDocument("firstName", "fn1") + .put("lastName", "ln1") + .put("birthDay", simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + .put("data", new byte[]{1, 2, 3}) + .put("list", Arrays.asList("one", "two", "three")) + .put("body", "a quick brown fox jump over the lazy dog"); + doc2 = createDocument("firstName", "fn2") + .put("lastName", "ln2") + .put("birthDay", simpleDateFormat.parse("2010-06-12T16:02:48.440Z")) + .put("data", new byte[]{3, 4, 3}) + .put("list", Arrays.asList("three", "four", "three")) + .put("body", "quick hello world from nitrite"); + doc3 = createDocument("firstName", "fn3") + .put("lastName", "ln2") + .put("birthDay", simpleDateFormat.parse("2014-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + + collection = db.getCollection("test"); + collection.remove(ALL); + } catch (Throwable t) { + log.error("Error while initializing test database", t); + } + } + + @After + public void clear() { + try { + if (collection != null && !collection.isDropped()) { + collection.close(); + } + if (db != null && !db.isClosed()) db.close(); + deleteDb(fileName); + } catch (Throwable t) { + log.error("Error while clearing test database", t); + } + } + + private void openDb() { + fstMarshaller.registerSerializer(DateTime.class, new JodaTimeKryoKeySerializer()); + + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(fileName) + .objectFormatter(fstMarshaller) + .build(); + + if (isSecured) { + db = Nitrite.builder() + .fieldSeparator(".") + .loadModule(storeModule) + .openOrCreate("test-user", "test-password"); + } else { + db = Nitrite.builder() + .fieldSeparator(".") + .loadModule(storeModule) + .openOrCreate(); + } + } + + protected WriteResult insert() { + return collection.insert(doc1, doc2, doc3); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexNegativeTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexNegativeTest.java new file mode 100644 index 000000000..746fe397b --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexNegativeTest.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.exceptions.UniqueConstraintException; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Date; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee + */ +public class CollectionCompoundIndexNegativeTest extends BaseCollectionTest { + + @Test(expected = UniqueConstraintException.class) + public void testCreateInvalidUniqueIndex() { + doc1 = createDocument("firstName", "fn3") + .put("lastName", "ln2") + .put("birthDay", new Date()) + .put("data", new byte[]{1, 2, 3}) + .put("list", Arrays.asList("one", "two", "three")) + .put("body", "a quick brown fox jump over the lazy dog"); + + collection.createIndex("lastName", "firstName"); + insert(); + } + + @Test(expected = UniqueConstraintException.class) + public void testCreateUniqueMultiKeyIndexOnArray() { + collection.createIndex("data", "lastName"); + insert(); + } + + @Test(expected = UniqueConstraintException.class) + public void testCreateOnInvalidField() { + insert(); + // multiple null value will be created + collection.createIndex( "my-value", "lastName"); + } + + @Test(expected = IndexingException.class) + public void testDropIndexOnNonIndexedField() { + collection.dropIndex("data", "firstName"); + } + + @Test(expected = IndexingException.class) + public void testRebuildIndexInvalid() { + collection.rebuildIndex("unknown", "firstName"); + } + + @Test(expected = IndexingException.class) + public void createMultipleIndexTypeOnSameFields() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "lastName", "firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName", "firstName"); + } + + @Test(expected = IndexingException.class) + public void testIndexAlreadyExists() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName", "lastName"); + assertTrue(collection.hasIndex("firstName")); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "firstName", "lastName"); + } + + @Test(expected = IndexingException.class) + public void testCreateCompoundTextIndex() { + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body", "lastName"); + } + + @Test(expected = IndexingException.class) + public void testCreateMultiKeyIndexSecondField() { + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName", "data"); + assertTrue(collection.hasIndex("lastName")); + + insert(); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexTest.java new file mode 100644 index 000000000..8d37792ed --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexTest.java @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import com.google.common.collect.Lists; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import java.util.Date; +import java.util.Random; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.awaitility.Awaitility.await; +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.Filter.and; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class CollectionCompoundIndexTest extends BaseCollectionTest { + @Test + public void testCreateAndCheckIndex() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName", "lastName"); + assertTrue(collection.hasIndex("firstName")); + assertTrue(collection.hasIndex("firstName", "lastName")); + assertFalse(collection.hasIndex("firstName", "lastName", "birthDay")); + assertFalse(collection.hasIndex("lastName")); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + insert(); + } + + @Test + public void testCreateMultiKeyIndexFirstField() { + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "data", "lastName"); + assertTrue(collection.hasIndex("data")); + assertTrue(collection.hasIndex("data", "lastName")); + assertFalse(collection.hasIndex("lastName")); + + insert(); + } + + @Test + public void testListIndexes() { + assertEquals(collection.listIndices().size(), 0); + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName", "lastName"); + assertEquals(collection.listIndices().size(), 1); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "firstName"); + assertEquals(collection.listIndices().size(), 2); + } + + @Test + public void testDropIndex() { + collection.createIndex("firstName", "lastName"); + assertTrue(collection.hasIndex("firstName", "lastName")); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.dropIndex("firstName"); + assertTrue(collection.hasIndex("firstName", "lastName")); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex("firstName"); + collection.dropIndex("firstName", "lastName"); + assertFalse(collection.hasIndex("firstName", "lastName")); + assertTrue(collection.hasIndex("firstName")); + + collection.dropIndex("firstName"); + assertFalse(collection.hasIndex("firstName")); + assertEquals(collection.listIndices().size(), 0); + } + + @Test + public void testHasIndex() { + assertFalse(collection.hasIndex("lastName")); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName", "firstName"); + assertTrue(collection.hasIndex("lastName")); + } + + @Test + public void testDropAllIndexes() { + collection.dropAllIndices(); + + collection.createIndex("firstName", "lastName"); + collection.createIndex("firstName"); + assertEquals(collection.listIndices().size(), 2); + + collection.dropAllIndices(); + assertEquals(collection.listIndices().size(), 0); + } + + @Test + public void testRebuildIndex() { + collection.createIndex("firstName", "lastName"); + assertTrue(collection.hasIndex("firstName", "lastName")); + assertTrue(collection.hasIndex("firstName")); + + insert(); + collection.rebuildIndex("firstName", "lastName"); + assertTrue(collection.hasIndex("firstName", "lastName")); + assertTrue(collection.hasIndex("firstName")); + } + + @Test + public void testDeleteWithIndex() { + collection.createIndex("firstName", "lastName"); + + insert(); + + WriteResult result = collection.remove(and(where("firstName").eq("fn1"), + where("lastName").eq("ln1"))); + assertEquals(result.getAffectedCount(), 1); + + result = collection.remove(and(where("firstName").eq("fn2"), + where("birthDay").gte(new Date()))); + assertEquals(result.getAffectedCount(), 0); + } + + @Test + public void testRebuildIndexOnRunningIndex() { + insert(); + db.getStore().subscribe(System.out::println); + + collection.createIndex("firstName", "lastName"); + collection.rebuildIndex("firstName", "lastName"); + + assertTrue(collection.hasIndex("firstName", "lastName")); + } + + @Test + public void testNullValuesInIndexedFields() { + collection.createIndex("firstName", "lastName"); + collection.createIndex("birthDay", "lastName"); + Document document = createDocument("firstName", null) + .put("lastName", "ln1") + .put("birthDay", new Date()) + .put("data", new byte[]{1, 2, 3}) + .put("list", Lists.newArrayList("one", "two", "three")) + .put("body", "a quick brown fox jump over the lazy dog"); + + insert(); + collection.insert(document); + + DocumentCursor cursor = collection.find(where("fistName").eq(null)); + assertEquals("ln1", cursor.firstOrNull().get("lastName", String.class)); + assertNull(cursor.firstOrNull().get("fistName", String.class)); + + document = createDocument("firstName", "fn4") + .put("lastName", null) + .put("birthDay", null) + .put("data", new byte[]{1, 2, 3}) + .put("list", Lists.newArrayList("one", "two", "three")) + .put("body", "a quick brown fox jump over the lazy dog"); + collection.insert(document); + + cursor = collection.find(where("lastName").eq(null)); + assertEquals("fn4", cursor.firstOrNull().get("firstName", String.class)); + assertNull(cursor.firstOrNull().get("fistName", String.class)); + + cursor = collection.find(and(where("lastName").eq(null), where("birthDay").eq(null))); + assertNull(cursor.firstOrNull().get("lastName", String.class)); + } + + @Test + public void testDropAllAndCreateIndex() { + collection.createIndex("firstName", "lastName"); + assertTrue(collection.hasIndex("firstName")); + + DocumentCursor cursor = collection.find(and(where("firstName").eq("fn1"), + where("lastName").eq("ln1"))); + FindPlan findPlan = cursor.getFindPlan(); + assertNotNull(findPlan.getIndexScanFilter()); + assertNull(findPlan.getCollectionScanFilter()); + + collection.dropAllIndices(); + cursor = collection.find(and(where("firstName").eq("fn1"), + where("lastName").eq("ln1"))); + findPlan = cursor.getFindPlan(); + assertNull(findPlan.getIndexScanFilter()); + assertNotNull(findPlan.getCollectionScanFilter()); + + collection.createIndex("firstName", "lastName"); + cursor = collection.find(and(where("firstName").eq("fn1"), + where("lastName").eq("ln1"))); + findPlan = cursor.getFindPlan(); + assertNotNull(findPlan.getIndexScanFilter()); + assertNull(findPlan.getCollectionScanFilter()); + } + + @Test + public void testIssue178() { + collection.dropAllIndices(); + collection.remove(Filter.ALL); + + Document doc1 = createDocument("field1", 5); + Document doc2 = createDocument("field1", 4.3).put("field2", 3.5); + Document doc3 = createDocument("field1", 0.03).put("field2", 5); + Document doc4 = createDocument("field1", 4).put("field2", 4.5); + Document doc5 = createDocument("field1", 5.0).put("field2", 5.0); + + collection.insert(doc1, doc2, doc3, doc4, doc5); + + DocumentCursor cursor = collection.find(and(where("field1").eq(0.03), + where("field2").eq(5))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(and(where("field1").eq(5), + where("field2").eq(null))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("field1").eq(5)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("field1").eq(5.0)); + assertEquals(cursor.size(), 1); + + collection.createIndex("field1", "field2"); + cursor = collection.find(and(where("field1").eq(0.03), + where("field2").eq(5))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(and(where("field1").eq(5), + where("field2").eq(null))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("field1").eq(5)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("field1").eq(5.0)); + assertEquals(cursor.size(), 1); + } + + @Test + public void testIndexEvent() { + NitriteCollection collection = db.getCollection("index-test"); + Random random = new Random(); + for (int i = 0; i < 10000; i++) { + Document document = createDocument("first", random.nextInt()) + .put("second", random.nextDouble()); + collection.insert(document); + } + + AtomicBoolean failed = new AtomicBoolean(false); + AtomicBoolean completed = new AtomicBoolean(false); + collection.subscribe(eventInfo -> { + switch (eventInfo.getEventType()) { + case Insert: + case Remove: + case Update: + failed.set(true); + break; + case IndexStart: + case IndexEnd: + completed.set(true); + break; + } + }); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "first", "second"); + assertEquals(collection.find().size(), 10000); + + await().until(completed::get); + assertFalse(failed.get()); + } + + @Test + public void testIndexAndSearchOnNullValues() { + NitriteCollection collection = db.getCollection("index-on-null"); + collection.insert(createDocument("first", null).put("second", 123).put("third", new Integer[]{1, 2, null})); + collection.insert(createDocument("first", "abcd").put("second", 456).put("third", new int[]{3, 1})); + collection.insert(createDocument("first", "xyz").put("second", 789).put("third", null)); + + collection.createIndex("third", "first"); + assertEquals(collection.find(where("first").eq(null)).size(), 1); + + assertEquals(collection.find(where("third").eq(null)).size(), 2); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionDeleteNegativeTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionDeleteNegativeTest.java new file mode 100644 index 000000000..9c9d9bd6a --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionDeleteNegativeTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.exceptions.NitriteIOException; +import org.dizitart.no2.exceptions.ValidationException; +import org.junit.Test; + +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionDeleteNegativeTest extends BaseCollectionTest { + @Test(expected = NitriteIOException.class) + public void testDrop() { + collection.drop(); + insert(); + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + } + + @Test(expected = FilterException.class) + public void testDeleteWithInvalidFilter() { + insert(); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + + WriteResult writeResult = collection.remove(where("lastName").gt(null)); + assertEquals(writeResult.getAffectedCount(), 0); + } + + @Test(expected = ValidationException.class) + public void testDeleteNullDocument() { + insert(); + + collection.remove((Document) null); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionDeleteTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionDeleteTest.java new file mode 100644 index 000000000..ca1660599 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionDeleteTest.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class CollectionDeleteTest extends BaseCollectionTest { + + @Test + public void testDelete() { + insert(); + + WriteResult writeResult = collection.remove(where("lastName").notEq(null)); + assertEquals(writeResult.getAffectedCount(), 3); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 0); + } + + @Test + public void testDeleteWithOptions() { + insert(); + + WriteResult writeResult = collection.remove(where("lastName").notEq(null), true); + assertEquals(writeResult.getAffectedCount(), 1); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 2); + } + + @Test + public void testDeleteWithNonMatchingFilter() { + insert(); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + + WriteResult writeResult = collection.remove(where("lastName").eq("a")); + assertEquals(writeResult.getAffectedCount(), 0); + } + + @Test + public void testDeleteInEmptyCollection() { + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 0); + + WriteResult writeResult = collection.remove(where("lastName").notEq(null)); + assertEquals(writeResult.getAffectedCount(), 0); + } + + @Test + public void testClear() { + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "firstName"); + insert(); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + assertTrue(collection.hasIndex("firstName")); + + boolean uniqueError = false; + try { + collection.insert(doc1); + } catch (Exception e) { + uniqueError = true; + } finally { + assertTrue(uniqueError); + } + + collection.remove(Filter.ALL); + + cursor = collection.find(); + assertEquals(cursor.size(), 0); + assertTrue(collection.hasIndex("firstName")); + + collection.insert(doc1); + cursor = collection.find(); + assertEquals(cursor.size(), 1); + assertTrue(collection.hasIndex("firstName")); + } + + @Test + public void testRemoveAll() { + insert(); + WriteResult writeResult = collection.remove((Filter) null); + assertEquals(writeResult.getAffectedCount(), 3); + } + + @Test + public void testRemoveDocument() { + insert(); + + WriteResult writeResult = collection.remove(where("firstName").eq("fn1")); + assertEquals(writeResult.getAffectedCount(), 1); + assertEquals(collection.size(), 2); + + writeResult = collection.remove(where("firstName").eq("fn2")); + assertEquals(writeResult.getAffectedCount(), 1); + assertEquals(collection.size(), 1); + + assertEquals(collection.find(where("firstName").eq("fn1")).size(), 0); + assertEquals(collection.find(where("firstName").eq("fn2")).size(), 0); + assertEquals(collection.find(where("firstName").eq("fn3")).size(), 1); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFieldIndexTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFieldIndexTest.java new file mode 100644 index 000000000..358e83a39 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFieldIndexTest.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee + */ +public class CollectionFieldIndexTest extends BaseCollectionTest { + @Test + public void testCollection() { + Document doc1 = Document.createDocument("name", "Anindya") + .put("color", new String[]{"red", "green", "blue"}) + .put("books", new Document[]{ + Document.createDocument("name", "Book ABCD") + .put("tag", new String[]{"tag1", "tag2"}), + Document.createDocument("name", "Book EFGH") + .put("tag", new String[]{"tag3", "tag1"}), + Document.createDocument("name", "No Tag") + }); + + Document doc2 = Document.createDocument("name", "Bill") + .put("color", new String[]{"purple", "yellow", "gray"}) + .put("books", new Document[]{ + Document.createDocument("name", "Book abcd") + .put("tag", new String[]{"tag4", "tag5"}), + Document.createDocument("name", "Book wxyz") + .put("tag", new String[]{"tag3", "tag1"}), + Document.createDocument("name", "No Tag 2") + }); + + Document doc3 = Document.createDocument("name", "John") + .put("color", new String[]{"black", "sky", "violet"}) + .put("books", new Document[]{ + Document.createDocument("name", "Book Mnop") + .put("tag", new String[]{"tag6", "tag2"}), + Document.createDocument("name", "Book ghij") + .put("tag", new String[]{"tag3", "tag7"}), + Document.createDocument("name", "No Tag") + }); + + NitriteCollection collection = db.getCollection("test"); + collection.createIndex("color"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "books.tag"); + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "books.name"); + + WriteResult writeResult = collection.insert(doc1, doc2, doc3); + assertEquals(writeResult.getAffectedCount(), 3); + + DocumentCursor documents = collection.find(where("color").eq("red")); + assertTrue(isSimilar(documents.firstOrNull(), doc1, "name", "color", "books")); + + documents = collection.find(where("books.name").text("abcd")); + assertEquals(documents.size(), 2); + + documents = collection.find(where("books.tag").eq("tag2")); + assertEquals(documents.size(), 2); + + documents = collection.find(where("books.tag").eq("tag5")); + assertEquals(documents.size(), 1); + + documents = collection.find(where("books.tag").eq("tag10")); + assertEquals(documents.size(), 0); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindByCompoundIndexTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindByCompoundIndexTest.java new file mode 100644 index 000000000..8fd30693e --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindByCompoundIndexTest.java @@ -0,0 +1,503 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.filters.AndFilter; +import org.dizitart.no2.filters.IndexScanFilter; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import java.text.ParseException; +import java.util.List; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.collection.FindOptions.orderBy; +import static org.dizitart.no2.filters.Filter.and; +import static org.dizitart.no2.filters.Filter.or; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class CollectionFindByCompoundIndexTest extends BaseCollectionTest { + + @Test + public void testFindByAndFilter() { + insert(); + collection.createIndex("list", "lastName", "firstName"); + DocumentCursor cursor = collection.find(and( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1"), + where("list").eq("four") + )); + + FindPlan findPlan = cursor.getFindPlan(); + assertNull(findPlan.getCollectionScanFilter()); + assertNotNull(findPlan.getIndexDescriptor()); + assertEquals(findPlan.getIndexDescriptor(), collection.listIndices().toArray()[0]); + + IndexScanFilter indexScanFilter = findPlan.getIndexScanFilter(); + assertEquals(indexScanFilter.getFilters().get(0), where("list").eq("four")); + assertEquals(indexScanFilter.getFilters().get(1), where("lastName").eq("ln2")); + assertEquals(indexScanFilter.getFilters().get(2), where("firstName").notEq("fn1")); + + List documents = cursor.toList(); + assertEquals(documents.size(), 1); + assertEquals(documents.get(0).get("body", String.class), "quick hello world from nitrite"); + } + + @Test + public void testFindByOrFilterAndFilter() { + insert(); + collection.createIndex("lastName", "firstName"); + DocumentCursor cursor = collection.find( + or( + and( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + ), + and( + where("firstName").eq("fn3"), + where("lastName").eq("ln2") + ) + ) + ); + + assertEquals(2, cursor.size()); + + FindPlan findPlan = cursor.getFindPlan(); + assertNull(findPlan.getIndexScanFilter()); + assertNull(findPlan.getCollectionScanFilter()); + assertNotNull(findPlan.getSubPlans()); + + assertEquals(2, findPlan.getSubPlans().size()); + assertNotNull(findPlan.getSubPlans().get(0).getIndexScanFilter()); + assertNotNull(findPlan.getSubPlans().get(1).getIndexScanFilter()); + + assertEquals(1, cursor.toList().stream().filter(d -> + d.get("firstName", String.class).equals("fn2") + && d.get("lastName", String.class).equals("ln2")).count()); + + assertEquals(1, cursor.toList().stream().filter(d -> + d.get("firstName", String.class).equals("fn3") + && d.get("lastName", String.class).equals("ln2")).count()); + } + + @Test + public void testFindByAndFilterOrFilter() { + insert(); + collection.createIndex("lastName", "firstName"); + DocumentCursor cursor = collection.find( + and( + or( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + ), + or( + where("firstName").eq("fn3"), + where("lastName").eq("ln2") + ) + ) + ); + + assertEquals(2, cursor.size()); + + FindPlan findPlan = cursor.getFindPlan(); + assertNull(findPlan.getIndexScanFilter()); + assertNotNull(findPlan.getCollectionScanFilter()); + assertTrue(findPlan.getSubPlans().isEmpty()); + + assertEquals(and( + or( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + ), + or( + where("firstName").eq("fn3"), + where("lastName").eq("ln2") + ) + ), findPlan.getCollectionScanFilter()); + } + + @Test + public void testFindByAndFilterAndFilter() { + insert(); + collection.createIndex("lastName", "firstName"); + DocumentCursor cursor = collection.find( + and( + and( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + ), + and( + where("firstName").eq("fn3"), + where("lastName").eq("ln2") + ) + ) + ); + + assertEquals(1, cursor.size()); + FindPlan findPlan = cursor.getFindPlan(); + + assertNotNull(findPlan.getIndexDescriptor()); + assertEquals(collection.listIndices().toArray()[0], findPlan.getIndexDescriptor()); + + assertNotNull(findPlan.getIndexScanFilter()); + assertEquals(findPlan.getIndexScanFilter().getFilters(), + ((AndFilter) and( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + )).getFilters()); + + assertNotNull(findPlan.getCollectionScanFilter()); + assertEquals(where("firstName").eq("fn3"), findPlan.getCollectionScanFilter()); + + assertTrue(findPlan.getSubPlans().isEmpty()); + + assertEquals(cursor.toList().get(0).get("firstName", String.class), "fn3"); + } + + @Test + public void testFindByOrFilter() throws ParseException { + // all or clause has index + insert(); + collection.createIndex("lastName", "firstName"); + collection.createIndex("firstName"); + collection.createIndex("birthDay"); + DocumentCursor cursor = collection.find( + or( + or( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + ), + where("birthDay").eq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")), + where("firstName").notEq("fn1") + ) + ); + + FindPlan findPlan = cursor.getFindPlan(); + assertEquals(3, findPlan.getSubPlans().size()); + assertEquals(3, cursor.size()); + } + + @Test + public void testFindOrNoIndex() throws ParseException { + // on of the or clause has no index + insert(); + collection.createIndex("lastName", "firstName"); + collection.createIndex("firstName"); + DocumentCursor cursor = collection.find( + or( + or( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + ), + where("birthDay").eq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")), + where("firstName").notEq("fn1") + ) + ); + + FindPlan findPlan = cursor.getFindPlan(); + assertEquals(0, findPlan.getSubPlans().size()); + assertEquals(3, cursor.size()); + } + + @Test + public void testFindAndNoIndex() throws ParseException { + // index at second field + insert(); + collection.createIndex("lastName", "firstName"); + DocumentCursor cursor = collection.find( + and( + where("firstName").notEq("fn1"), + where("birthDay").eq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + ) + ); + + FindPlan findPlan = cursor.getFindPlan(); + assertNull(findPlan.getIndexScanFilter()); + assertNull(findPlan.getIndexDescriptor()); + + assertNotNull(findPlan.getCollectionScanFilter()); + assertEquals(0, cursor.size()); + } + + @Test + public void testSortByIndex() throws ParseException { + // multiple field sort in both direction + collection.createIndex("lastName", "birthDay"); + + Document doc = createDocument("firstName", "fn4") + .put("lastName", "ln3") + .put("birthDay", simpleDateFormat.parse("2016-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + collection.insert(doc); + collection.insert(doc3); + collection.insert(doc1); + collection.insert(doc2); + + DocumentCursor cursor = collection.find( + and( + where("lastName").notEq("ln1"), + where("birthDay").notEq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + ), + orderBy("lastName", SortOrder.Ascending) + .thenOrderBy("birthDay", SortOrder.Descending) + ); + + List documents = cursor.toList(); + assertEquals(3, documents.size()); + + Document document = documents.get(0); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2014-04-17T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(1); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2010-06-12T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(2); + assertEquals("ln3", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2016-04-17T16:02:48.440Z"), document.get("birthDay")); + + FindPlan findPlan = cursor.getFindPlan(); + assertTrue(findPlan.getBlockingSortOrder().isEmpty()); + assertNull(findPlan.getCollectionScanFilter()); + assertNotNull(findPlan.getIndexDescriptor()); + assertFalse(findPlan.getIndexScanOrder().get("lastName")); + + // reverse scan + assertTrue(findPlan.getIndexScanOrder().get("birthDay")); + } + + @Test + public void testBlockingSort() throws ParseException { + // multiple field sort in memory + + Document doc = createDocument("firstName", "fn4") + .put("lastName", "ln3") + .put("birthDay", simpleDateFormat.parse("2016-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + collection.insert(doc); + collection.insert(doc3); + collection.insert(doc1); + collection.insert(doc2); + + DocumentCursor cursor = collection.find( + and( + where("lastName").notEq("ln1"), + where("birthDay").notEq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + ), + orderBy("lastName", SortOrder.Ascending) + .thenOrderBy("birthDay", SortOrder.Descending) + ); + + List documents = cursor.toList(); + assertEquals(3, documents.size()); + + Document document = documents.get(0); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2014-04-17T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(1); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2010-06-12T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(2); + assertEquals("ln3", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2016-04-17T16:02:48.440Z"), document.get("birthDay")); + + FindPlan findPlan = cursor.getFindPlan(); + List> blockingSortOrder = findPlan.getBlockingSortOrder(); + assertEquals(2, blockingSortOrder.size()); + + Pair pair = blockingSortOrder.get(0); + assertEquals("lastName", pair.getFirst()); + assertEquals(SortOrder.Ascending, pair.getSecond()); + + pair = blockingSortOrder.get(1); + assertEquals("birthDay", pair.getFirst()); + assertEquals(SortOrder.Descending, pair.getSecond()); + + assertNotNull(findPlan.getCollectionScanFilter()); + assertNull(findPlan.getIndexDescriptor()); + assertNull(findPlan.getIndexScanOrder()); + } + + @Test + public void testSortNotCoveredByIndex() throws ParseException { + // some field sort by index, some by memory + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + + Document doc = createDocument("firstName", "fn4") + .put("lastName", "ln3") + .put("birthDay", simpleDateFormat.parse("2016-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + collection.insert(doc); + collection.insert(doc3); + collection.insert(doc1); + collection.insert(doc2); + + DocumentCursor cursor = collection.find( + and( + where("lastName").notEq("ln1"), + where("birthDay").notEq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + ), + orderBy("lastName", SortOrder.Ascending) + .thenOrderBy("birthDay", SortOrder.Descending) + ); + + List documents = cursor.toList(); + assertEquals(3, documents.size()); + + Document document = documents.get(0); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2014-04-17T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(1); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2010-06-12T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(2); + assertEquals("ln3", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2016-04-17T16:02:48.440Z"), document.get("birthDay")); + + FindPlan findPlan = cursor.getFindPlan(); + List> blockingSortOrder = findPlan.getBlockingSortOrder(); + assertEquals(2, blockingSortOrder.size()); + + Pair pair = blockingSortOrder.get(0); + assertEquals("lastName", pair.getFirst()); + assertEquals(SortOrder.Ascending, pair.getSecond()); + + pair = blockingSortOrder.get(1); + assertEquals("birthDay", pair.getFirst()); + assertEquals(SortOrder.Descending, pair.getSecond()); + + assertNotNull(findPlan.getCollectionScanFilter()); + assertNotNull(findPlan.getIndexDescriptor()); + assertNull(findPlan.getIndexScanOrder()); + } + + @Test + public void testSortByIndexPrefix() throws ParseException { + collection.createIndex("lastName", "birthDay"); + + Document doc = createDocument("firstName", "fn4") + .put("lastName", "ln3") + .put("birthDay", simpleDateFormat.parse("2016-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + collection.insert(doc); + collection.insert(doc3); + collection.insert(doc1); + collection.insert(doc2); + + DocumentCursor cursor = collection.find( + and( + where("lastName").notEq("ln1"), + where("birthDay").notEq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + ), + orderBy("lastName", SortOrder.Ascending) + ); + + List documents = cursor.toList(); + assertEquals(3, documents.size()); + + Document document = documents.get(0); + assertEquals("ln2", document.get("lastName")); + // duplicate birthday will have natural sort order - ascending + assertEquals(simpleDateFormat.parse("2010-06-12T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(1); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2014-04-17T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(2); + assertEquals("ln3", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2016-04-17T16:02:48.440Z"), document.get("birthDay")); + + FindPlan findPlan = cursor.getFindPlan(); + assertTrue(findPlan.getBlockingSortOrder().isEmpty()); + assertNull(findPlan.getCollectionScanFilter()); + assertNotNull(findPlan.getIndexDescriptor()); + assertFalse(findPlan.getIndexScanOrder().get("lastName")); + } + + @Test + public void testLimitAndSkip() throws ParseException { + // test skip and limit + + collection.createIndex("lastName", "birthDay"); + + Document doc = createDocument("firstName", "fn4") + .put("lastName", "ln3") + .put("birthDay", simpleDateFormat.parse("2016-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + collection.insert(doc); + collection.insert(doc3); + collection.insert(doc1); + collection.insert(doc2); + + DocumentCursor cursor = collection.find( + and( + where("lastName").notEq("ln1"), + where("birthDay").notEq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + ), + orderBy("lastName", SortOrder.Ascending) + .thenOrderBy("birthDay", SortOrder.Descending) + .skip(2) + .limit(1) + ); + + List documents = cursor.toList(); + assertEquals(1, documents.size()); + + Document document = documents.get(0); + assertEquals("ln3", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2016-04-17T16:02:48.440Z"), document.get("birthDay")); + + FindPlan findPlan = cursor.getFindPlan(); + assertTrue(findPlan.getBlockingSortOrder().isEmpty()); + assertNull(findPlan.getCollectionScanFilter()); + assertNotNull(findPlan.getIndexDescriptor()); + assertFalse(findPlan.getIndexScanOrder().get("lastName")); + assertEquals(2L, (long)findPlan.getSkip()); + assertEquals(1L, (long)findPlan.getLimit()); + + // reverse scan + assertTrue(findPlan.getIndexScanOrder().get("birthDay")); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindByIndexNegativeTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindByIndexNegativeTest.java new file mode 100644 index 000000000..76b84a0e6 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindByIndexNegativeTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionFindByIndexNegativeTest extends BaseCollectionTest { + @Test(expected = FilterException.class) + public void testFindTextWithWildCardMultipleWord() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + + DocumentCursor cursor = collection.find(where("body").text("*ipsum dolor*")); + assertEquals(cursor.size(), 1); + } + + @Test(expected = FilterException.class) + public void testFindTextWithOnlyWildCard() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + + DocumentCursor cursor = collection.find(where("body").text("*")); + assertEquals(cursor.size(), 1); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindBySingleFieldIndexTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindBySingleFieldIndexTest.java new file mode 100644 index 000000000..cbef67e26 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindBySingleFieldIndexTest.java @@ -0,0 +1,423 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import com.github.javafaker.Faker; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import static org.dizitart.no2.integration.TestUtil.isSorted; +import static org.dizitart.no2.collection.FindOptions.orderBy; +import static org.dizitart.no2.filters.Filter.and; +import static org.dizitart.no2.filters.Filter.or; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionFindBySingleFieldIndexTest extends BaseCollectionTest { + + @Test + public void testFindByUniqueIndex() throws ParseException { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "firstName"); + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("firstName").eq("fn10")); + assertEquals(cursor.size(), 0); + + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "birthDay"); + cursor = collection.find(where("birthDay").gt( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").gte( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lt( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").lte( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lte( + new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").lt( + new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").gt( + new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("birthDay").gte( + new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find( + where("birthDay").lte(new Date()) + .and(where("firstName").eq("fn1"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + where("birthDay").lte(new Date()) + .or(where("firstName").eq("fn12"))); + assertEquals(cursor.size(), 3); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + )); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + ).not()); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").eq((byte) 4)); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").lt(4)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("firstName").notIn("fn1", "fn2")); + assertEquals(cursor.size(), 1); + } + + @Test + public void testFindByNonUniqueIndex() throws ParseException { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "lastName"); + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "birthDay"); + + DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("lastName").eq("ln20")); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("birthDay").gt( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").gte( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lt( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").lte( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lte( + new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").lt( + new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").gt( + new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("birthDay").gte( + new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find( + where("birthDay").lte(new Date()) + .and(where("firstName").eq("fn1"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + where("birthDay").lte(new Date()) + .or(where("firstName").eq("fn12"))); + assertEquals(cursor.size(), 3); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + )); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + ).not()); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").eq((byte) 4)); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").lt(4)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("firstName").notIn("fn1", "fn2")); + assertEquals(cursor.size(), 1); + } + + @Test + public void testFindByFullTextIndexAfterInsert() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + + DocumentCursor cursor = collection.find(where("body").text("Lorem")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("body").text("nosql")); + assertEquals(cursor.size(), 0); + + collection.dropIndex("body"); + boolean filterException = false; + try { + collection.find(where("body").text("Lorem")).toList(); + } catch (FilterException fe) { + filterException = true; + } finally { + assertTrue(filterException); + } + } + + @Test + public void testFindByFullTextIndexBeforeInsert() { + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + insert(); + + DocumentCursor cursor = collection.find(where("body").text("Lorem")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("body").text("quick brown")); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("body").text("nosql")); + assertEquals(cursor.size(), 0); + + collection.dropIndex("body"); + boolean filterException = false; + try { + collection.find(where("body").text("Lorem")).toList(); + } catch (FilterException fe) { + filterException = true; + } finally { + assertTrue(filterException); + } + } + + @Test + public void testFindByIndexSortAscending() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "birthDay"); + + DocumentCursor cursor = collection.find(orderBy("birthDay", SortOrder.Ascending)); + assertEquals(cursor.size(), 3); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, true)); + } + + @Test + public void testFindByIndexSortDescending() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "birthDay"); + + DocumentCursor cursor = collection.find(orderBy("birthDay", SortOrder.Descending)); + assertEquals(cursor.size(), 3); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, false)); + } + + @Test + public void testFindByIndexLimitAndSort() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "birthDay"); + + DocumentCursor cursor = collection.find( + orderBy("birthDay", SortOrder.Descending) + .skip(1) + .limit(2) + ); + assertEquals(cursor.size(), 2); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, false)); + + cursor = collection.find(orderBy("birthDay", SortOrder.Ascending).skip(1).limit(2)); + assertEquals(cursor.size(), 2); + dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, true)); + + cursor = collection.find(orderBy("firstName", SortOrder.Ascending).skip(0).limit(30)); + assertEquals(cursor.size(), 3); + List nameList = new ArrayList<>(); + for (Document document : cursor) { + nameList.add(document.get("firstName", String.class)); + } + assertTrue(isSorted(nameList, true)); + } + + @Test + public void testFindAfterDroppedIndex() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "firstName"); + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + + collection.dropIndex("firstName"); + cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + } + + @Test + public void testFindTextWithWildCard() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + + DocumentCursor cursor = collection.find(where("body").text("Lo")); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("body").text("Lo*")); + assertEquals(cursor.size(), 1); // Lorem + + cursor = collection.find(where("body").text("*rem")); + assertEquals(cursor.size(), 1); // lorem + + cursor = collection.find(where("body").text("*or*")); + assertEquals(cursor.size(), 2); + } + + @Test + public void testFindTextWithEmptyString() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + + DocumentCursor cursor = collection.find(where("body").text("")); + assertEquals(cursor.size(), 0); + } + + @Test + public void testFindWithOrIndexed() { + NitriteCollection collection = db.getCollection("testFindWithOrIndexed"); + Document doc1 = Document.createDocument("firstName", "John").put("lastName", "Doe"); + Document doc2 = Document.createDocument("firstName", "Jane").put("lastName", "Doe"); + Document doc3 = Document.createDocument("firstName", "Jonas").put("lastName", "Doe"); + Document doc4 = Document.createDocument("firstName", "Johan").put("lastName", "Day"); + + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "firstName"); + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "lastName"); + + collection.insert(doc1, doc2, doc3, doc4); + + DocumentCursor cursor = collection.find(where("firstName").eq("John").or(where("lastName").eq("Day"))); + assertEquals(cursor.size(), 2); + + List list = cursor.toList(); + assertEquals(list.size(), 2); + } + + @Test + public void testIssue45() { + NitriteCollection collection = db.getCollection("testIssue45"); + Faker faker = new Faker(); + String text1 = faker.lorem().paragraph() + " quick brown"; + String text2 = faker.lorem().paragraph() + " fox jump"; + String text3 = faker.lorem().paragraph() + " over lazy"; + String text4 = faker.lorem().paragraph() + " dog"; + + List list1 = Arrays.asList(text1, text2); + List list2 = Arrays.asList(text1, text2, text3); + List list3 = Arrays.asList(text2, text3); + List list4 = Arrays.asList(text1, text2, text3, text4); + + Document doc1 = Document.createDocument("firstName", "John").put("notes", list1); + Document doc2 = Document.createDocument("firstName", "Jane").put("notes", list2); + Document doc3 = Document.createDocument("firstName", "Jonas").put("notes", list3); + Document doc4 = Document.createDocument("firstName", "Johan").put("notes", list4); + + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "notes"); + collection.insert(doc1, doc2, doc3, doc4); + + DocumentCursor cursor = collection.find(where("notes").text("fox")); + assertEquals(cursor.size(), 4); + + cursor = collection.find(where("notes").text("dog")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("notes").text("lazy")); + assertEquals(cursor.size(), 3); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindNegativeTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindNegativeTest.java new file mode 100644 index 000000000..8d446cf0f --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindNegativeTest.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.exceptions.ValidationException; +import org.junit.Test; + +import java.util.Date; +import java.util.List; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.collection.FindOptions.orderBy; +import static org.dizitart.no2.collection.FindOptions.skipBy; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionFindNegativeTest extends BaseCollectionTest { + @Test(expected = ValidationException.class) + public void testFindFilterInvalidIndex() { + insert(); + collection.find(where("data.9").eq(4)).toList(); + } + + @Test(expected = ValidationException.class) + public void testFindOptionsNegativeOffset() { + insert(); + collection.find(skipBy(-1).limit(1)); + } + + @Test(expected = ValidationException.class) + public void testFindOptionsNegativeSize() { + insert(); + collection.find(skipBy(0).limit(-1)); + } + + @Test + public void testFindOptionsInvalidOffset() { + insert(); + assertEquals(collection.find(skipBy(10).limit(1)).size(), 0); + } + + @Test(expected = ValidationException.class) + public void testFindInvalidSort() { + insert(); + collection.find(orderBy("data", SortOrder.Descending)).toList(); + } + + @Test(expected = FilterException.class) + public void testFindTextFilterNonIndexed() { + insert(); + collection.find(where("body").text("Lorem")).toList(); + } + + @Test(expected = FilterException.class) + public void testFindWithRegexInvalidValue() { + insert(); + DocumentCursor cursor = collection.find(where("birthDay").regex("hello")); + assertEquals(cursor.size(), 1); + } + + @Test(expected = ValidationException.class) + public void testInvalidProjection() { + insert(); + DocumentCursor cursor = collection.find(where("birthDay").lte(new Date()), + orderBy("firstName", SortOrder.Ascending).skip(0).limit(3)); + + Document projection = createDocument("firstName", null) + .put("lastName", "ln2"); + + cursor.project(projection); + } + + @Test(expected = UnsupportedOperationException.class) + public void testToListAdd() { + insert(); + DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); + List documents = cursor.toList(); + documents.add(createDocument()); + } + + @Test(expected = UnsupportedOperationException.class) + public void testToListRemove() { + insert(); + DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); + List documents = cursor.toList(); + documents.clear(); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindTest.java new file mode 100644 index 000000000..f5e5a2c04 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionFindTest.java @@ -0,0 +1,825 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.joda.time.DateTime; +import org.junit.Test; + +import java.text.Collator; +import java.text.ParseException; +import java.util.*; +import java.util.stream.Collectors; + +import static org.dizitart.no2.integration.TestUtil.isSorted; +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.collection.FindOptions.*; +import static org.dizitart.no2.common.Constants.*; +import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; +import static org.dizitart.no2.filters.Filter.*; +import static org.dizitart.no2.filters.FluentFilter.$; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.*; + +public class CollectionFindTest extends BaseCollectionTest { + + private static Document trimMeta(Document document) { + document.remove(DOC_ID); + document.remove(DOC_REVISION); + document.remove(DOC_MODIFIED); + document.remove(DOC_SOURCE); + return document; + } + + @Test + public void testFindAll() { + insert(); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + } + + @Test + public void testFindWithFilter() throws ParseException { + insert(); + + DocumentCursor cursor = collection.find(where("birthDay").gt( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").gte( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lt( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").lte( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lte( + new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").lt( + new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").gt( + new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("birthDay").gte( + new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find( + where("birthDay").lte(new Date()) + .and(where("firstName").eq("fn1"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + where("birthDay").lte(new Date()) + .or(where("firstName").eq("fn12"))); + assertEquals(cursor.size(), 3); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + )); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + ).not()); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").eq((byte) 4)); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").lt(4)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("firstName").notIn("fn1", "fn2")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(ALL.not()); + assertEquals(cursor.size(), 0); + } + + @Test + public void testFindWithSkipLimit() { + insert(); + + DocumentCursor cursor = collection.find(skipBy(0).limit(1)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(skipBy(1).limit(3)); + assertEquals(cursor.size(), 2); + + cursor = collection.find(skipBy(0).limit(30)); + assertEquals(cursor.size(), 3); + + cursor = collection.find(skipBy(2).limit(3)); + assertEquals(cursor.size(), 1); + } + + @Test + public void testFindWithSkip() { + insert(); + + DocumentCursor cursor = collection.find(skipBy(0)); + assertEquals(cursor.size(), 3); + + cursor = collection.find(skipBy(1)); + assertEquals(cursor.size(), 2); + + cursor = collection.find(skipBy(30)); + assertEquals(cursor.size(), 0); + + cursor = collection.find(skipBy(2)); + assertEquals(cursor.size(), 1); + + boolean invalid = false; + try { + cursor = collection.find(skipBy(-1)); + assertEquals(cursor.size(), 1); + } catch (ValidationException e) { + invalid = true; + } + assertTrue(invalid); + } + + @Test + public void testFindWithLimit() { + insert(); + + DocumentCursor cursor = collection.find(limitBy(0)); + assertEquals(cursor.size(), 0); + + cursor = collection.find(limitBy(1)); + assertEquals(cursor.size(), 1); + + boolean invalid = false; + try { + cursor = collection.find(limitBy(-1)); + assertEquals(cursor.size(), 1); + } catch (ValidationException e) { + invalid = true; + } + assertTrue(invalid); + + cursor = collection.find(limitBy(30)); + assertEquals(cursor.size(), 3); + } + + @Test + public void testFindSortAscending() { + insert(); + + DocumentCursor cursor = collection.find(orderBy("birthDay", SortOrder.Ascending)); + assertEquals(cursor.size(), 3); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, true)); + } + + @Test + public void testFindSortDescending() { + insert(); + + DocumentCursor cursor = collection.find(orderBy("birthDay", SortOrder.Descending)); + assertEquals(cursor.size(), 3); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, false)); + } + + @Test + public void testFindLimitAndSort() { + insert(); + + DocumentCursor cursor = collection.find(orderBy("birthDay", SortOrder.Descending).skip(1).limit(2)); + assertEquals(cursor.size(), 2); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, false)); + + cursor = collection.find(orderBy("birthDay", SortOrder.Ascending).skip(1).limit(2)); + assertEquals(cursor.size(), 2); + dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, true)); + + cursor = collection.find(orderBy("firstName", SortOrder.Ascending).skip(0).limit(30)); + assertEquals(cursor.size(), 3); + List nameList = new ArrayList<>(); + for (Document document : cursor) { + nameList.add(document.get("firstName", String.class)); + } + assertTrue(isSorted(nameList, true)); + } + + @Test + public void testFindSortOnNonExistingField() { + insert(); + DocumentCursor cursor = collection.find(orderBy("my-value", SortOrder.Descending)); + assertEquals(cursor.size(), 3); + } + + @Test + public void testFindInvalidField() { + insert(); + DocumentCursor cursor = collection.find(where("myField").eq("myData")); + assertEquals(cursor.size(), 0); + } + + @Test + public void testFindInvalidFieldWithInvalidAccessor() { + insert(); + DocumentCursor cursor = collection.find(where("myField.0").eq("myData")); + assertEquals(cursor.size(), 0); + } + + @Test + public void testFindLimitAndSortInvalidField() { + insert(); + DocumentCursor cursor = collection.find(orderBy("birthDay2", SortOrder.Descending).skip(1).limit(2)); + assertEquals(cursor.size(), 2); + } + + @Test + public void testGetById() { + collection.insert(doc1); + NitriteId id = NitriteId.createId("1"); + Document document = collection.getById(id); + assertNull(document); + + document = collection.find().firstOrNull(); + + assertEquals(document.get(DOC_ID), document.getId().getIdValue()); + assertEquals(document.get("firstName"), "fn1"); + assertEquals(document.get("lastName"), "ln1"); + assertArrayEquals((byte[]) document.get("data"), new byte[]{1, 2, 3}); + assertEquals(document.get("body"), "a quick brown fox jump over the lazy dog"); + } + + @Test + public void testFindWithFilterAndOption() { + insert(); + DocumentCursor cursor = collection.find(where("birthDay").lte(new Date()), + orderBy("firstName", SortOrder.Ascending).skip(1).limit(2)); + assertEquals(cursor.size(), 2); + } + + @Test + public void testFindTextWithRegex() { + insert(); + DocumentCursor cursor = collection.find(where("body").regex("hello")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("body").regex("test")); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("body").regex("^hello$")); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("body").regex(".*")); + assertEquals(cursor.size(), 3); + } + + @Test + public void testProject() { + insert(); + DocumentCursor cursor = collection.find(where("birthDay").lte(new Date()), + orderBy("firstName", SortOrder.Ascending).skip(0).limit(3)); + int iteration = 0; + for (Document document : cursor) { + switch (iteration) { + case 0: + assertTrue(isSimilar(document, doc1, "firstName", "lastName", "birthDay", "data", "list", "body")); + break; + case 1: + assertTrue(isSimilar(document, doc2, "firstName", "lastName", "birthDay", "data", "list", "body")); + break; + case 2: + assertTrue(isSimilar(document, doc3, "firstName", "lastName", "birthDay", "data", "list", "body")); + break; + } + iteration++; + } + assertEquals(iteration, 3); + } + + @Test + public void testProjectWithCustomDocument() { + insert(); + DocumentCursor cursor = collection.find(where("birthDay").lte(new Date()), + orderBy("firstName", SortOrder.Ascending).skip(0).limit(3)); + + Document projection = createDocument("firstName", null) + .put("lastName", null); + + Iterable documents = cursor.project(projection); + int iteration = 0; + for (Document document : documents) { + assertTrue(document.containsKey("firstName")); + assertTrue(document.containsKey("lastName")); + + assertFalse(document.containsKey("_id")); + assertFalse(document.containsKey("birthDay")); + assertFalse(document.containsKey("data")); + assertFalse(document.containsKey("body")); + + switch (iteration) { + case 0: + assertEquals(document.get("firstName"), "fn1"); + assertEquals(document.get("lastName"), "ln1"); + break; + case 1: + assertEquals(document.get("firstName"), "fn2"); + assertEquals(document.get("lastName"), "ln2"); + break; + case 2: + assertEquals(document.get("firstName"), "fn3"); + assertEquals(document.get("lastName"), "ln2"); + break; + } + iteration++; + } + assertEquals(iteration, 3); + } + + @Test + public void testFindWithArrayEqual() { + insert(); + DocumentCursor ids = collection.find(where("data").eq(new byte[]{3, 4, 3})); + assertNotNull(ids); + assertEquals(ids.size(), 1); + } + + @Test + public void testFindWithArrayEqualFailForWrongCardinality() { + insert(); + DocumentCursor ids = collection.find(where("data").eq(new byte[]{4, 3, 3})); + assertNotNull(ids); + assertEquals(ids.size(), 0); + } + + @Test + public void testFindWithIterableEqual() { + insert(); + DocumentCursor ids = collection.find(where("list").eq( + new ArrayList() {{ + add("three"); + add("four"); + add("three"); + }})); + assertNotNull(ids); + assertEquals(ids.size(), 1); + } + + @Test + public void testFindWithIterableEqualFailForWrongCardinality() { + insert(); + DocumentCursor ids = collection.find(where("list").eq( + new ArrayList() {{ + add("four"); + add("three"); + add("three"); + }})); + assertNotNull(ids); + assertEquals(ids.size(), 0); + } + + @Test + public void testFindInArray() { + insert(); + DocumentCursor ids = collection.find(where("data").elemMatch($.gte(2).and($.lt(5)))); + assertNotNull(ids); + assertEquals(ids.size(), 3); + + ids = collection.find(where("data").elemMatch($.gt(2).or($.lte(5)))); + assertNotNull(ids); + assertEquals(ids.size(), 3); + + ids = collection.find(where("data").elemMatch($.gt(1).and($.lt(4)))); + assertNotNull(ids); + assertEquals(ids.size(), 2); + } + + @Test + public void testFindInList() { + insert(); + DocumentCursor ids = collection.find(where("list").elemMatch($.regex("three"))); + assertNotNull(ids); + assertEquals(ids.size(), 2); + + ids = collection.find(where("list").elemMatch($.regex("hello"))); + assertNotNull(ids); + assertEquals(ids.size(), 0); + + ids = collection.find(where("list").elemMatch($.regex("hello").not())); + assertNotNull(ids); + assertEquals(ids.size(), 2); + } + + @Test + public void testElemMatchFilter() { + Document doc1 = createDocument("productScores", new Document[]{ + createDocument("product", "abc").put("score", 10), + createDocument("product", "xyz").put("score", 5) + }).put("strArray", new String[]{"a", "b"}); + + Document doc2 = createDocument("productScores", new Document[]{ + createDocument("product", "abc").put("score", 8), + createDocument("product", "xyz").put("score", 7) + }).put("strArray", new String[]{"d", "e"}); + + Document doc3 = createDocument("productScores", new Document[]{ + createDocument("product", "abc").put("score", 7), + createDocument("product", "xyz").put("score", 8) + }).put("strArray", new String[]{"a", "f"}); + + NitriteCollection prodCollection = db.getCollection("prodScore"); + prodCollection.insert(doc1, doc2, doc3); + + List documentList = prodCollection.find(where("productScores") + .elemMatch(where("product").eq("xyz").and(where("score").gte(8)))).toList(); + + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").lte(8).not())).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("product").eq("xyz").or(where("score").gte(8)))).toList(); + assertEquals(documentList.size(), 3); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("product").eq("xyz"))).toList(); + assertEquals(documentList.size(), 3); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").gte(10))).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").gt(8))).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").lt(7))).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").lte(7))).toList(); + assertEquals(documentList.size(), 3); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").in(7, 8))).toList(); + assertEquals(documentList.size(), 2); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").notIn(7, 8))).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("product").regex("xyz"))).toList(); + assertEquals(documentList.size(), 3); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.eq("a"))).toList(); + assertEquals(documentList.size(), 2); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.eq("a").or($.eq("f").or($.eq("b"))).not())).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.gt("e"))).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.gte("e"))).toList(); + assertEquals(documentList.size(), 2); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.lte("b"))).toList(); + assertEquals(documentList.size(), 2); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.lt("a"))).toList(); + assertEquals(documentList.size(), 0); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.in("a", "f"))).toList(); + assertEquals(documentList.size(), 2); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.regex("a"))).toList(); + assertEquals(documentList.size(), 2); + + } + + @Test + public void testNotEqualFilter() { + Document document = createDocument("abc", "123"); + document.put("xyz", null); + + collection.insert(document); + DocumentCursor cursor = collection.find(where("abc").eq("123")); + assertEquals(cursor.size(), 1); + assertEquals(cursor.toList().size(), 1); + + cursor = collection.find(where("xyz").eq(null)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("abc").notEq(null)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("abc").notEq(null).and(where("xyz").eq(null))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("abc").eq(null).and(where("xyz").notEq(null))); + assertEquals(cursor.size(), 0); + + collection.remove(ALL); + + document = createDocument("field", "two"); + document.put(DOC_REVISION, 1482225343161L); + + collection.insert(document); + Document projection = collection.find( + where(DOC_REVISION).gte(1482225343160L) + .and(where(DOC_REVISION).lte(1482225343162L) + .and(where(DOC_REVISION).notEq(null)))) + .firstOrNull(); + + assertNull(projection); + } + + @Test + public void testFilterAll() { + DocumentCursor cursor = collection.find(ALL); + assertNotNull(cursor); + assertEquals(cursor.size(), 0); + + insert(); + cursor = collection.find(ALL); + assertNotNull(cursor); + assertEquals(cursor.size(), 3); + } + + @Test + public void testIssue72() { + NitriteCollection coll = db.getCollection("test"); + coll.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "id"); + coll.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "group"); + + coll.remove(ALL); + + Document doc = createDocument().put("id", "test-1").put("group", "groupA"); + assertEquals(1, coll.insert(doc).getAffectedCount()); + + doc = createDocument().put("id", "test-2").put("group", "groupA").put("startTime", DateTime.now()); + assertEquals(1, coll.insert(doc).getAffectedCount()); + + DocumentCursor cursor = coll.find(where("group").eq("groupA"), + orderBy("startTime", SortOrder.Descending)); + assertEquals(2, cursor.size()); + assertNull(cursor.toList().get(1).get("startTime")); + assertNotNull(cursor.toList().get(0).get("startTime")); + + cursor = coll.find(where("group").eq("groupA"), + orderBy("startTime", SortOrder.Ascending)); + assertEquals(2, cursor.size()); + assertNull(cursor.toList().get(0).get("startTime")); + assertNotNull(cursor.toList().get(1).get("startTime")); + } + + @Test + public void testIssue93() { + NitriteCollection coll = db.getCollection("orderByOnNullableColumn2"); + + coll.remove(ALL); + + Document doc = createDocument().put("id", "test-2").put("group", "groupA"); + assertEquals(1, coll.insert(doc).getAffectedCount()); + + doc = createDocument().put("id", "test-1").put("group", "groupA"); + assertEquals(1, coll.insert(doc).getAffectedCount()); + + DocumentCursor cursor = coll.find(where("group").eq("groupA"), + orderBy("startTime", SortOrder.Descending)); + assertEquals(2, cursor.size()); + } + + @Test + public void testNullOrderWithAllNull() { + NitriteCollection coll = db.getCollection("test"); + + coll.remove(ALL); + + Document doc = createDocument().put("id", "test-2").put("group", "groupA"); + assertEquals(1, coll.insert(doc).getAffectedCount()); + + doc = createDocument().put("id", "test-1").put("group", "groupA"); + assertEquals(1, coll.insert(doc).getAffectedCount()); + + DocumentCursor cursor = coll.find(where("group").eq("groupA"), + orderBy("startTime", SortOrder.Descending)); + assertEquals(2, cursor.size()); + } + + @Test + public void testDefaultNullOrder() { + NitriteCollection coll = db.getCollection("test"); + try { + coll.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "startTime"); + } catch (IndexingException e) { + // ignore + } + + coll.remove(ALL); + + Document doc1 = createDocument().put("id", "test-1").put("group", "groupA"); + assertEquals(1, coll.insert(doc1).getAffectedCount()); + + Document doc2 = createDocument().put("id", "test-2").put("group", "groupA").put("startTime", DateTime.now()); + assertEquals(1, coll.insert(doc2).getAffectedCount()); + + Document doc3 = createDocument().put("id", "test-3").put("group", "groupA").put("startTime", DateTime.now().plusMinutes(1)); + assertEquals(1, coll.insert(doc3).getAffectedCount()); + + DocumentCursor cursor = coll.find(where("group").eq("groupA"), + orderBy("startTime", SortOrder.Descending)); + assertEquals(3, cursor.size()); + assertThat(Arrays.asList(doc3, doc2, doc1), + is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); + + + cursor = coll.find(where("group").eq("groupA"), + orderBy("startTime", SortOrder.Ascending)); + assertEquals(3, cursor.size()); + assertThat(Arrays.asList(doc1, doc2, doc3), + is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); + } + + @Test + public void testFindFilterInvalidAccessor() { + insert(); + DocumentCursor cursor = collection.find(where("lastName.name").eq("ln2")); + assertEquals(cursor.size(), 0); + } + + @Test + public void testIssue144() { + Document doc1 = createDocument().put("id", "test-1").put("fruit", "Apple"); + Document doc2 = createDocument().put("id", "test-2").put("fruit", "Ôrange"); + Document doc3 = createDocument().put("id", "test-3").put("fruit", "Pineapple"); + + NitriteCollection coll = db.getCollection("test"); + coll.insert(doc1, doc2, doc3); + + DocumentCursor cursor = coll.find(orderBy("fruit", SortOrder.Ascending) + .collator(Collator.getInstance(Locale.FRANCE))); + assertEquals(cursor.toList().get(1).get("fruit"), "Ôrange"); + } + + @Test + public void testIdSet() { + insert(); + DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("lastName").eq("ln1")); + assertEquals(cursor.size(), 1); + + Document byId = cursor.iterator().next(); + assertEquals(byId.get("lastName"), "ln1"); + } + + @Test + public void testCollectionField() { + Document document = createDocument("name", "John") + .put("tags", new Document[]{ + createDocument("type", "example").put("other", "value"), + createDocument("type", "another-example").put("other", "some-other-value") + }); + + NitriteCollection example = db.getCollection("example"); + example.insert(document); + + document = createDocument("name", "Jane") + .put("tags", new Document[]{ + createDocument("type", "example2").put("other", "value2"), + createDocument("type", "another-example2").put("other", "some-other-value2") + }); + example.insert(document); + + DocumentCursor cursor = example.find(where("tags").elemMatch(where("type").eq("example"))); + for (Document doc : cursor) { + assertNotNull(doc); + assertEquals(doc.get("name"), "John"); + } + } + + @Test + public void testBetweenFilter() { + Document doc1 = createDocument("age", 31).put("tag", "one"); + Document doc2 = createDocument("age", 32).put("tag", "two"); + Document doc3 = createDocument("age", 33).put("tag", "three"); + Document doc4 = createDocument("age", 34).put("tag", "four"); + Document doc5 = createDocument("age", 35).put("tag", "five"); + + NitriteCollection collection = db.getCollection("tag"); + collection.insert(doc1, doc2, doc3, doc4, doc5); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "age"); + + DocumentCursor cursor = collection.find(where("age").between(31, 35)); + assertEquals(cursor.size(), 5); + + cursor = collection.find(where("age").between(31, 35, false)); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("age").between(31, 35, false, true)); + assertEquals(cursor.size(), 4); + + cursor = collection.find(where("age").between(31, 35, false).not()); + assertEquals(cursor.size(), 2); + } + + @Test + public void testByIdFilter() { + Document doc1 = createDocument("age", 31).put("tag", "one"); + Document doc2 = createDocument("age", 32).put("tag", "two"); + Document doc3 = createDocument("age", 33).put("tag", "three"); + Document doc4 = createDocument("age", 34).put("tag", "four"); + Document doc5 = createDocument("age", 35).put("tag", "five"); + + NitriteCollection collection = db.getCollection("tag"); + collection.insert(doc1, doc2, doc3, doc4, doc5); + + List documentList = collection.find().toList(); + Document document = documentList.get(0); + NitriteId nitriteId = document.getId(); + + Document result = collection.find(byId(nitriteId)).firstOrNull(); + assertEquals(document, result); + + result = collection.find(and(byId(nitriteId), where("age").notEq(null))).firstOrNull(); + assertEquals(document, result); + + result = collection.find(or(byId(nitriteId), where("tag").eq(document.get("tag")))).firstOrNull(); + assertEquals(document, result); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionIndexNegativeTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionIndexNegativeTest.java new file mode 100644 index 000000000..f6ce8612e --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionIndexNegativeTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.exceptions.UniqueConstraintException; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionIndexNegativeTest extends BaseCollectionTest { + + @Test(expected = UniqueConstraintException.class) + public void testCreateInvalidUniqueIndex() { + collection.createIndex("lastName"); + assertTrue(collection.hasIndex("lastName")); + insert(); + } + + @Test(expected = UniqueConstraintException.class) + public void testCreateIndexOnArray() { + collection.createIndex("data"); + assertTrue(collection.hasIndex("data")); + // data array field has repetition, so unique constraint exception + insert(); + } + + @Test(expected = UniqueConstraintException.class) + public void testCreateOnInvalidField() { + insert(); + collection.createIndex("my-value"); + assertTrue(collection.hasIndex("my-value")); + } + + @Test(expected = IndexingException.class) + public void testCreateFullTextOnNonTextField() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "birthDay"); + assertTrue(collection.hasIndex("birthDay")); + } + + @Test(expected = IndexingException.class) + public void testDropIndexOnNonIndexedField() { + collection.dropIndex("data"); + } + + @Test(expected = IndexingException.class) + public void testRebuildIndexInvalid() { + collection.rebuildIndex("unknown"); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionIndexTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionIndexTest.java new file mode 100644 index 000000000..247a1705a --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionIndexTest.java @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Random; +import java.util.concurrent.Callable; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionIndexTest extends BaseCollectionTest { + + @Test + public void testCollection() { + Document doc1 = Document.createDocument("name", "Anindya") + .put("color", new String[]{"red", "green", "blue"}) + .put("books", new Document[]{ + Document.createDocument("name", "Book ABCD") + .put("tag", new String[]{"tag1", "tag2"}), + Document.createDocument("name", "Book EFGH") + .put("tag", new String[]{"tag3", "tag1"}), + Document.createDocument("name", "No Tag") + }); + + Document doc2 = Document.createDocument("name", "Bill") + .put("color", new String[]{"purple", "yellow", "gray"}) + .put("books", new Document[]{ + Document.createDocument("name", "Book abcd") + .put("tag", new String[]{"tag4", "tag5"}), + Document.createDocument("name", "Book wxyz") + .put("tag", new String[]{"tag3", "tag1"}), + Document.createDocument("name", "No Tag 2") + }); + + Document doc3 = Document.createDocument("name", "John") + .put("color", new String[]{"black", "sky", "violet"}) + .put("books", new Document[]{ + Document.createDocument("name", "Book Mnop") + .put("tag", new String[]{"tag6", "tag2"}), + Document.createDocument("name", "Book ghij") + .put("tag", new String[]{"tag3", "tag7"}), + Document.createDocument("name", "No Tag") + }); + + NitriteCollection collection = db.getCollection("test"); + collection.createIndex("color"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "books.tag"); + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "books.name"); + + WriteResult writeResult = collection.insert(doc1, doc2, doc3); + assertEquals(writeResult.getAffectedCount(), 3); + + DocumentCursor documents = collection.find(where("color").eq("red")); + assertTrue(isSimilar(documents.firstOrNull(), doc1, "name", "color", "books")); + + documents = collection.find(where("books.name").text("abcd")); + assertEquals(documents.size(), 2); + + documents = collection.find(where("books.tag").eq("tag2")); + assertEquals(documents.size(), 2); + + documents = collection.find(where("books.tag").eq("tag5")); + assertEquals(documents.size(), 1); + + documents = collection.find(where("books.tag").eq("tag10")); + assertEquals(documents.size(), 0); + } + + @Test + public void testCreateIndex() { + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + + collection.createIndex("birthDay", null); + assertTrue(collection.hasIndex("birthDay")); + + insert(); + } + + @Test + public void testListIndexes() { + assertEquals(collection.listIndices().size(), 0); + + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + + assertEquals(collection.listIndices().size(), 3); + } + + @Test + public void testDropIndex() { + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.dropIndex("firstName"); + assertFalse(collection.hasIndex("firstName")); + } + + @Test + public void testDropAllIndexes() { + collection.dropAllIndices(); + + testCreateIndex(); + assertEquals(collection.listIndices().size(), 4); + + collection.dropAllIndices(); + assertEquals(collection.listIndices().size(), 0); + } + + @Test + public void testHasIndex() { + assertFalse(collection.hasIndex("lastName")); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + assertFalse(collection.hasIndex("body")); + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + } + + @Test + public void testDeleteWithIndex() { + collection.createIndex("firstName"); + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + + insert(); + + WriteResult result = collection.remove(where("firstName").eq("fn1")); + assertEquals(result.getAffectedCount(), 1); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 2); + + result = collection.remove(where("body").text("Lorem")); + assertEquals(result.getAffectedCount(), 1); + + cursor = collection.find(); + assertEquals(cursor.size(), 1); + } + + @Test + public void testRebuildIndex() { + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + insert(); + Collection indices = collection.listIndices(); + for (IndexDescriptor idx : indices) { + collection.rebuildIndex(idx.getIndexFields().getFieldNames().toArray(new String[0])); + } + } + + private Callable bodyIndexingCompleted() { + return () -> !collection.isIndexing("body"); + } + + @Test + public void testNullValueInIndexedField() { + collection.createIndex("firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "birthDay"); + insert(); + + Document document = createDocument("firstName", null) + .put("lastName", "ln1") + .put("birthDay", null) + .put("data", new byte[]{1, 2, 3}) + .put("list", new ArrayList() {{ + add("one"); + add("two"); + add("three"); + }}) + .put("body", "a quick brown fox jump over the lazy dog"); + + collection.insert(document); + } + + @Test + public void testDropAllAndCreateIndex() { + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + collection.dropAllIndices(); + assertFalse(collection.hasIndex("firstName")); + + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection = db.getCollection("test"); + assertTrue(collection.hasIndex("firstName")); + } + + @Test + public void testIssue178() { + collection.dropAllIndices(); + collection.remove(Filter.ALL); + + Document doc1 = createDocument("field", 5); + Document doc2 = createDocument("field", 4.3); + Document doc3 = createDocument("field", 0.03); + Document doc4 = createDocument("field", 4); + Document doc5 = createDocument("field", 5.0); + + collection.insert(doc1, doc2, doc3, doc4, doc5); + + DocumentCursor cursor = collection.find(where("field").eq(5)); + assertEquals(cursor.size(), 1); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "field"); + + cursor = collection.find(where("field").eq(5)); + assertEquals(cursor.size(), 1); + } + + @Test + public void testIndexEvent() { + NitriteCollection collection = db.getCollection("index-test"); + Random random = new Random(); + for (int i = 0; i < 10000; i++) { + Document document = createDocument("first", random.nextInt()) + .put("second", random.nextDouble()); + collection.insert(document); + } + + collection.subscribe(eventInfo -> { + switch (eventInfo.getEventType()) { + case Insert: + fail("wrong event Insert"); + break; + case Update: + fail("wrong event Update"); + break; + case Remove: + fail("wrong event Remove"); + break; + case IndexStart: + case IndexEnd: + break; + } + assertTrue(eventInfo.getItem() instanceof String); + System.out.println(eventInfo.getEventType() + " for field " + eventInfo.getItem()); + }); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "first"); + assertEquals(collection.find().size(), 10000); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "second"); + assertEquals(collection.find().size(), 10000); + } + + @Test + public void testIndexAndSearchOnNullValues() { + NitriteCollection collection = db.getCollection("index-on-null"); + collection.insert(createDocument("first", null).put("second", 123).put("third", new Integer[]{1, 2, null})); + collection.insert(createDocument("first", "abcd").put("second", 456).put("third", new int[]{3, 1})); + collection.insert(createDocument("first", "xyz").put("second", 789).put("third", null)); + + collection.createIndex("first"); + assertEquals(collection.find(where("first").eq(null)).size(), 1); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "third"); + assertEquals(collection.find(where("third").eq(null)).size(), 2); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionInsertNegativeTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionInsertNegativeTest.java new file mode 100644 index 000000000..02358caf6 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionInsertNegativeTest.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.exceptions.UniqueConstraintException; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionInsertNegativeTest extends BaseCollectionTest { + @Test(expected = UniqueConstraintException.class) + public void testMultipleInsert() { + WriteResult result = collection.insert(doc1, doc2, doc3); + assertEquals(result.getAffectedCount(), 3); + Document document = collection.find().firstOrNull(); + collection.insert(document); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionInsertTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionInsertTest.java new file mode 100644 index 000000000..cd9558946 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionInsertTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.common.WriteResult; +import org.junit.Test; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.common.Constants.DOC_ID; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class CollectionInsertTest extends BaseCollectionTest { + + @Test + public void testInsert() { + WriteResult result = collection.insert(doc1, doc2, doc3); + assertEquals(result.getAffectedCount(), 3); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + + for (Document document : cursor) { + assertNotNull(document.get("firstName")); + assertNotNull(document.get("lastName")); + assertNotNull(document.get("birthDay")); + assertNotNull(document.get("data")); + assertNotNull(document.get("body")); + assertNotNull(document.get(DOC_ID)); + } + } + + @Test + public void testInsertHeteroDocs() { + Document document = createDocument("test", "Nitrite Test"); + + WriteResult result = collection.insert(doc1, doc2, doc3, document); + assertEquals(result.getAffectedCount(), 4); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionJoinTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionJoinTest.java new file mode 100644 index 000000000..caff44d61 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionJoinTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import lombok.extern.slf4j.Slf4j; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.Lookup; +import org.dizitart.no2.common.RecordStream; +import org.junit.Before; +import org.junit.Test; + +import java.util.Collection; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.Filter.ALL; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +@Slf4j +public class CollectionJoinTest extends BaseCollectionTest { + private NitriteCollection foreignCollection; + + @Before + @Override + public void setUp() { + try { + super.setUp(); + foreignCollection = db.getCollection("foreign"); + foreignCollection.remove(ALL); + + Document fdoc1 = createDocument("fName", "fn1") + .put("address", "ABCD Street") + .put("telephone", "123456789"); + + Document fdoc2 = createDocument("fName", "fn2") + .put("address", "XYZ Street") + .put("telephone", "000000000"); + + Document fdoc3 = createDocument("fName", "fn2") + .put("address", "Some other Street") + .put("telephone", "7893141321"); + + foreignCollection.insert(fdoc1, fdoc2, fdoc3); + } catch (Throwable t) { + log.error("Error while initializing test database", t); + } + } + + @Test + @SuppressWarnings("unchecked") + public void testJoinAll() { + insert(); + + Lookup lookup = new Lookup(); + lookup.setLocalField("firstName"); + lookup.setForeignField("fName"); + lookup.setTargetField("personalDetails"); + + RecordStream result = collection.find().join(foreignCollection.find(), lookup); + assertEquals(result.size(), 3); + + for (Document document : result) { + if (document.get("firstName") == "fn1") { + Collection personalDetails = (Collection) document.get("personalDetails"); + assertNotNull(personalDetails); + assertEquals(personalDetails.size(), 1); + Object[] details = personalDetails.toArray(); + assertEquals(((Document) details[0]).get("telephone"), "123456789"); + } else if (document.get("firstName") == "fn2") { + Collection personalDetails = (Collection) document.get("personalDetails"); + assertNotNull(personalDetails); + assertEquals(personalDetails.size(), 2); + Object[] details = personalDetails.toArray(); + for (Object o : details) { + Document d = (Document) o; + if (d.get("address").equals("XYZ Street")) { + assertEquals(d.get("telephone"), "000000000"); + } else { + assertEquals(d.get("telephone"), "7893141321"); + } + } + } else if (document.get("firstName") == "fn3") { + assertNull(document.get("personalDetails")); + } + System.out.println(document); + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionSingleFieldIndexNegativeTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionSingleFieldIndexNegativeTest.java new file mode 100644 index 000000000..b459e469b --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionSingleFieldIndexNegativeTest.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.exceptions.UniqueConstraintException; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionSingleFieldIndexNegativeTest extends BaseCollectionTest { + + @Test(expected = UniqueConstraintException.class) + public void testCreateInvalidUniqueIndex() { + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + insert(); + } + + @Test(expected = UniqueConstraintException.class) + public void testCreateIndexOnArray() { + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "data"); + assertTrue(collection.hasIndex("data")); + // data array field has repetition, so unique constraint exception + insert(); + } + + @Test(expected = UniqueConstraintException.class) + public void testCreateOnInvalidField() { + insert(); + // multiple null value will be created + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "my-value"); + assertTrue(collection.hasIndex("my-value")); + } + + @Test(expected = IndexingException.class) + public void testCreateFullTextOnNonTextField() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "birthDay"); + assertTrue(collection.hasIndex("birthDay")); + } + + @Test(expected = IndexingException.class) + public void testDropIndexOnNonIndexedField() { + collection.dropIndex("data"); + } + + @Test(expected = IndexingException.class) + public void testRebuildIndexInvalid() { + collection.rebuildIndex("unknown"); + } + + @Test(expected = IndexingException.class) + public void createMultipleIndexTypeOnSameField() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "lastName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionSingleFieldIndexTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionSingleFieldIndexTest.java new file mode 100644 index 000000000..fe37845e1 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionSingleFieldIndexTest.java @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Random; +import java.util.concurrent.Callable; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.awaitility.Awaitility.await; +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionSingleFieldIndexTest extends BaseCollectionTest { + + @Test + public void testCreateIndex() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + + collection.createIndex("birthDay"); + assertTrue(collection.hasIndex("birthDay")); + + insert(); + } + + @Test + public void testListIndexes() { + assertEquals(collection.listIndices().size(), 0); + + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + + assertEquals(collection.listIndices().size(), 3); + } + + @Test + public void testDropIndex() { + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.dropIndex("firstName"); + assertFalse(collection.hasIndex("firstName")); + } + + @Test + public void testDropAllIndexes() { + collection.dropAllIndices(); + + testCreateIndex(); + assertEquals(collection.listIndices().size(), 4); + + collection.dropAllIndices(); + assertEquals(collection.listIndices().size(), 0); + } + + @Test + public void testHasIndex() { + assertFalse(collection.hasIndex("lastName")); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + assertFalse(collection.hasIndex("body")); + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + } + + @Test + public void testDeleteWithIndex() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName"); + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + + insert(); + + WriteResult result = collection.remove(where("firstName").eq("fn1")); + assertEquals(result.getAffectedCount(), 1); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 2); + + result = collection.remove(where("body").text("Lorem")); + assertEquals(result.getAffectedCount(), 1); + + cursor = collection.find(); + assertEquals(cursor.size(), 1); + } + + @Test + public void testRebuildIndex() { + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + insert(); + Collection indices = collection.listIndices(); + for (IndexDescriptor idx : indices) { + collection.rebuildIndex(idx.getIndexFields().getFieldNames().toArray(new String[0])); + } + } + + @Test + public void testRebuildIndexOnRunningIndex() { + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + insert(); + collection.rebuildIndex("body"); + + boolean error = false; + try { + collection.rebuildIndex("body"); + } catch (IndexingException ie) { + error = true; + } finally { + assertFalse(error); + await().until(bodyIndexingCompleted()); + } + } + + private Callable bodyIndexingCompleted() { + return () -> !collection.isIndexing("body"); + } + + @Test + public void testNullValueInIndexedField() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "birthDay"); + insert(); + + Document document = createDocument("firstName", null) + .put("lastName", "ln1") + .put("birthDay", null) + .put("data", new byte[]{1, 2, 3}) + .put("list", new ArrayList() {{ + add("one"); + add("two"); + add("three"); + }}) + .put("body", "a quick brown fox jump over the lazy dog"); + + collection.insert(document); + } + + @Test + public void testDropAllAndCreateIndex() { + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + collection.dropAllIndices(); + assertFalse(collection.hasIndex("firstName")); + + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection = db.getCollection("test"); + assertTrue(collection.hasIndex("firstName")); + } + + @Test + public void testIssue178() { + collection.dropAllIndices(); + collection.remove(Filter.ALL); + + Document doc1 = createDocument("field", 5); + Document doc2 = createDocument("field", 4.3); + Document doc3 = createDocument("field", 0.03); + Document doc4 = createDocument("field", 4); + Document doc5 = createDocument("field", 5.0); + + collection.insert(doc1, doc2, doc3, doc4, doc5); + + DocumentCursor cursor = collection.find(where("field").eq(5)); + assertEquals(cursor.size(), 1); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "field"); + + cursor = collection.find(where("field").eq(5)); + assertEquals(cursor.size(), 1); + } + + @Test + public void testIndexEvent() { + NitriteCollection collection = db.getCollection("index-test"); + Random random = new Random(); + for (int i = 0; i < 10000; i++) { + Document document = createDocument("first", random.nextInt()) + .put("second", random.nextDouble()); + collection.insert(document); + } + + AtomicBoolean failed = new AtomicBoolean(false); + AtomicBoolean completed = new AtomicBoolean(false); + collection.subscribe(eventInfo -> { + switch (eventInfo.getEventType()) { + case Insert: + case Remove: + case Update: + failed.set(true); + break; + case IndexStart: + case IndexEnd: + completed.set(true); + break; + } + }); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "first"); + assertEquals(collection.find().size(), 10000); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "second"); + assertEquals(collection.find().size(), 10000); + + await().until(completed::get); + assertFalse(failed.get()); + } + + @Test + public void testIndexAndSearchOnNullValues() { + NitriteCollection collection = db.getCollection("index-on-null"); + collection.insert(createDocument("first", null).put("second", 123).put("third", new Integer[]{1, 2, null})); + collection.insert(createDocument("first", "abcd").put("second", 456).put("third", new int[]{3, 1})); + collection.insert(createDocument("first", "xyz").put("second", 789).put("third", null)); + + collection.createIndex(indexOptions(IndexType.UNIQUE), "first"); + assertEquals(collection.find(where("first").eq(null)).size(), 1); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "third"); + assertEquals(collection.find(where("third").eq(null)).size(), 2); + } + + @Test + public void testCreateCompoundAndSingleFieldIndexOnSameField() { + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName", "firstName"); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionUpdateTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionUpdateTest.java new file mode 100644 index 000000000..86bff59b5 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionUpdateTest.java @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.UpdateOptions; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.exceptions.NitriteIOException; +import org.dizitart.no2.exceptions.NotIdentifiableException; +import org.dizitart.no2.exceptions.UniqueConstraintException; +import org.dizitart.no2.filters.Filter; +import org.junit.Test; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + +public class CollectionUpdateTest extends BaseCollectionTest { + + @Test + public void testUpdate() { + insert(); + + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + for (Document document : cursor) { + assertEquals(document.get("lastName"), "ln1"); + } + + WriteResult updateResult = collection.update(where("firstName").eq("fn1"), + createDocument("lastName", "new-last-name")); + assertEquals(updateResult.getAffectedCount(), 1); + + cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + for (Document document : cursor) { + assertEquals(document.get("lastName"), "new-last-name"); + } + } + + @Test(expected = NotIdentifiableException.class) + public void testUpsertWithoutId() { + insert(); + Document update = createDocument("lastName", "ln4"); + WriteResult writeResult = collection.update(update, false); + assertEquals(writeResult.getAffectedCount(), 0); + assertEquals(collection.size(), 3); + } + + @Test + public void testUpsert() { + insert(); + assertEquals(collection.size(), 3); + + Document update = createDocument("lastName", "ln4"); + WriteResult writeResult = collection.update(update, true); + assertEquals(writeResult.getAffectedCount(), 1); + assertEquals(collection.size(), 4); + + Document document = collection.find(where("lastName").eq("ln4")) + .firstOrNull(); + assertTrue(isSimilar(document, update, "lastName")); + } + + @Test + public void testOptionUpsert() { + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 0); + + WriteResult updateResult = collection.update(where("firstName").eq("fn1"), + doc1, UpdateOptions.updateOptions(true)); + assertEquals(updateResult.getAffectedCount(), 1); + + cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + for (Document document : cursor) { + assertTrue(isSimilar(document, doc1, "firstName", "lastName", "birthDay", "data", "list", "body")); + } + } + + @Test + public void testUpdateMultiple() { + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 0); + + insert(); + + Document document = createDocument("lastName", "newLastName1"); + WriteResult updateResult = collection.update(where("firstName").eq("fn1").not(), + document); + assertEquals(updateResult.getAffectedCount(), 2); + + cursor = collection.find(where("lastName").eq("newLastName1")); + assertEquals(cursor.size(), 2); + } + + @Test + public void testUpdateWithOptionsUpsertFalse() { + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 0); + + UpdateOptions updateOptions = new UpdateOptions(); + updateOptions.setInsertIfAbsent(false); + + WriteResult updateResult = collection.update(where("firstName").eq("fn1"), + doc1, updateOptions); + assertEquals(updateResult.getAffectedCount(), 0); + + cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 0); + } + + @Test + public void testUpdateMultipleWithJustOnceFalse() { + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 0); + + insert(); + + UpdateOptions updateOptions = new UpdateOptions(); + updateOptions.setJustOnce(false); + + Document document = createDocument("lastName", "newLastName1"); + WriteResult updateResult = collection.update(where("firstName").eq("fn1").not(), + document, updateOptions); + assertEquals(updateResult.getAffectedCount(), 2); + + cursor = collection.find(where("lastName").eq("newLastName1")); + assertEquals(cursor.size(), 2); + } + + @Test + public void testUpdateMultipleWithJustOnceTrue() { + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 0); + + insert(); + + UpdateOptions updateOptions = new UpdateOptions(); + updateOptions.setJustOnce(true); + + Document document = createDocument("lastName", "newLastName1"); + collection.update(where("firstName").eq("fn1").not(), + document, updateOptions); + } + + @Test + public void testUpdateWithNewField() { + insert(); + + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + for (Document document : cursor) { + assertEquals(document.get("lastName"), "ln1"); + } + + WriteResult updateResult = collection.update(where("firstName").eq("fn1"), + createDocument("new-value", "new-value-value")); + assertEquals(updateResult.getAffectedCount(), 1); + + cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + for (Document document : cursor) { + assertEquals(document.get("new-value"), "new-value-value"); + } + } + + @Test + public void testUpdateInvalidFilter() { + insert(); + + DocumentCursor cursor = collection.find(where("lastName").eq("ln1")); + assertEquals(cursor.size(), 1); + for (Document document : cursor) { + assertEquals(document.get("firstName"), "fn1"); + } + + // to check if NitriteId is valid. + WriteResult updateResult = collection.update(where("some-value").eq("some-value"), + createDocument("lastName", "new-last-name")); + assertEquals(updateResult.getAffectedCount(), 0); + } + + @Test + public void updateAfterAttributeRemoval() { + NitriteCollection coll = db.getCollection("test_updateAfterAttributeRemoval"); + coll.remove(Filter.ALL); + + Document doc = createDocument().put("id", "test-1").put("group", "groupA"); + assertEquals(1, coll.insert(doc).getAffectedCount()); + + Document savedDoc1 = coll.find().firstOrNull(); + assertNotNull(savedDoc1); + + Document clonedDoc1 = savedDoc1.clone(); + assertEquals(savedDoc1, clonedDoc1); + + clonedDoc1.put("group", null); +// clonedDoc1.remove("group"); + assertEquals(1, coll.update(clonedDoc1).getAffectedCount()); + + Document savedDoc2 = coll.find(Filter.ALL).firstOrNull(); + assertNotNull(savedDoc2); + assertNull(savedDoc2.get("group")); + } + + @Test(expected = NotIdentifiableException.class) + public void testUpdateWithoutId() { + NitriteCollection collection = db.getCollection("test"); + Document document = createDocument("test", "test123"); + collection.update(document); + } + + @Test(expected = NotIdentifiableException.class) + public void testRemoveWithoutId() { + NitriteCollection collection = db.getCollection("test"); + Document document = createDocument("test", "test123"); + collection.remove(document); + } + + @Test(expected = NitriteIOException.class) + public void testRegisterListenerAfterDrop() { + NitriteCollection collection = db.getCollection("test"); + collection.drop(); + collection.subscribe(changeInfo -> fail("should not happen")); + } + + @Test(expected = NitriteIOException.class) + public void testRegisterListenerAfterClose() throws Exception { + NitriteCollection collection = db.getCollection("test"); + collection.close(); + collection.subscribe(changeInfo -> fail("should not happen")); + } + + @Test(expected = UniqueConstraintException.class) + public void testIssue151() { + Document doc1 = createDocument().put("id", "test-1").put("fruit", "Apple"); + Document doc2 = createDocument().put("id", "test-2").put("fruit", "Ôrange"); + NitriteCollection coll = db.getCollection("test"); + coll.insert(doc1, doc2); + + coll.createIndex("fruit"); + + assertEquals(coll.find(where("fruit").eq("Apple")).size(), 1); + + Document doc3 = coll.find(where("id").eq("test-2")).firstOrNull(); + + doc3.put("fruit", "Apple"); + coll.update(doc3); + + assertEquals(coll.find(where("fruit").eq("Apple")).size(), 1); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/FieldProcessorTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/FieldProcessorTest.java new file mode 100644 index 000000000..0055f97ac --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/FieldProcessorTest.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.common.crypto.AESEncryptor; +import org.dizitart.no2.common.crypto.Encryptor; +import org.dizitart.no2.common.processors.Processor; +import org.dizitart.no2.common.processors.StringFieldEncryptionProcessor; +import org.dizitart.no2.exceptions.NitriteSecurityException; +import org.dizitart.no2.store.NitriteMap; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.nio.charset.StandardCharsets; +import java.util.Date; +import java.util.List; + +import static org.dizitart.no2.common.util.Iterables.toList; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class FieldProcessorTest extends BaseCollectionTest { + + private Encryptor encryptor; + private NitriteCollection collection; + private Processor cvvProcessor; + + @Before + public void setUp() { + super.setUp(); + + encryptor = new AESEncryptor("s3k4e8"); + cvvProcessor = new Processor() { + @Override + public Document processBeforeWrite(Document document) { + String cvv = document.get("cvv", String.class); + String encryptedCvv = encryptor.encrypt(cvv.getBytes(StandardCharsets.UTF_8)); + document.put("cvv", encryptedCvv); + return document; + } + + @Override + public Document processAfterRead(Document document) { + String encryptedCvv = document.get("cvv", String.class); + String cvv = encryptor.decrypt(encryptedCvv); + document.put("cvv", cvv); + return document; + } + }; + StringFieldEncryptionProcessor creditCardProcessor = new StringFieldEncryptionProcessor(encryptor); + creditCardProcessor.addFields("creditCardNumber"); + + collection = db.getCollection("encryption-test"); + collection.addProcessor(creditCardProcessor); + + Document document = Document.createDocument("name", "John Doe") + .put("creditCardNumber", "5548960345687452") + .put("cvv", "007") + .put("expiryDate", new Date()); + collection.insert(document); + + document = Document.createDocument("name", "Jane Doe") + .put("creditCardNumber", "5500960345687452") + .put("cvv", "008") + .put("expiryDate", new Date()); + collection.insert(document); + + collection.addProcessor(cvvProcessor); + } + + @Test + public void testFieldEncryptionInNitriteMap() { + NitriteMap nitriteMap = collection.getStore().openMap("encryption-test", + NitriteId.class, Document.class); + + List documents = toList(nitriteMap.values()); + for (Document document : documents) { + if (document.get("creditCardNumber", String.class).equalsIgnoreCase("5548960345687452")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("creditCardNumber", String.class).equalsIgnoreCase("5500960345687452")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("cvv", String.class).equalsIgnoreCase("008")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("cvv", String.class).equalsIgnoreCase("007")) { + Assert.fail("unencrypted secret text found"); + } + } + } + + @Test + public void testSuccessfulDecryption() { + Document document = collection.find(where("name").eq("Jane Doe")).firstOrNull(); + assertNotNull(document); + + assertEquals(document.get("creditCardNumber", String.class), "5500960345687452"); + assertEquals(document.get("cvv", String.class), "008"); + + document = collection.find(where("name").eq("John Doe")).firstOrNull(); + assertNotNull(document); + + assertEquals(document.get("creditCardNumber", String.class), "5548960345687452"); + assertEquals(document.get("cvv", String.class), "007"); + } + + @Test(expected = NitriteSecurityException.class) + public void testFailedDecryption() { + Encryptor wrongEncryptor = new AESEncryptor("secret"); + + collection = db.getCollection("encryption-test"); + collection.addProcessor(new Processor() { + @Override + public Document processBeforeWrite(Document document) { + String creditCardNumber = document.get("creditCardNumber", String.class); + String encryptedCreditCardNumber = encryptor.encrypt(creditCardNumber.getBytes(StandardCharsets.UTF_8)); + document.put("creditCardNumber", encryptedCreditCardNumber); + return document; + } + + @Override + public Document processAfterRead(Document document) { + String encryptedCreditCardNumber = document.get("creditCardNumber", String.class); + String creditCardNumber = wrongEncryptor.decrypt(encryptedCreditCardNumber); + document.put("creditCardNumber", creditCardNumber); + return document; + } + }); + + Document document = Document.createDocument("name", "John Doe") + .put("creditCardNumber", "5548960345687452") + .put("cvv", "007") + .put("expiryDate", new Date()); + collection.insert(document); + + document = Document.createDocument("name", "Jane Doe") + .put("creditCardNumber", "5500960345687452") + .put("cvv", "008") + .put("expiryDate", new Date()); + collection.insert(document); + + collection.find(where("name").eq("Jane Doe")).firstOrNull(); + } + + @Test + public void testSearchOnEncryptedField() { + Document document = collection.find(where("cvv").eq("008")).firstOrNull(); + assertNull(document); + } + + @Test + public void testUpdateEncryptedField() { + Document document = Document.createDocument("name", "John Doe") + .put("creditCardNumber", "00000000000000") + .put("cvv", "007") + .put("expiryDate", new Date()); + + WriteResult writeResult = collection.update(where("name").eq("John Doe"), document); + assertEquals(writeResult.getAffectedCount(), 1); + + document = collection.find(where("name").eq("John Doe")).firstOrNull(); + assertNotNull(document); + + assertEquals(document.get("creditCardNumber", String.class), "00000000000000"); + assertEquals(document.get("cvv", String.class), "007"); + } + + @Test + public void testIndexOnEncryptedField() { + collection.createIndex("cvv"); + Document document = collection.find(where("cvv").eq("008")).firstOrNull(); + assertNull(document); + } + + @Test + public void testRemoveProcessor() { + Document document = collection.find(where("cvv").eq("008")).firstOrNull(); + assertNull(document); + + collection.removeProcessor(cvvProcessor); + + document = collection.find(where("cvv").eq("008")).firstOrNull(); + assertNotNull(document); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/NitriteCollectionTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/NitriteCollectionTest.java new file mode 100644 index 000000000..ad3534435 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/collection/NitriteCollectionTest.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.meta.Attributes; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee + */ +public class NitriteCollectionTest extends BaseCollectionTest { + + @Test + public void testAttributes() { + NitriteCollection collection = db.getCollection("test"); + + Attributes attributes = new Attributes("test"); + collection.setAttributes(attributes); + + assertEquals(collection.getAttributes(), attributes); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/event/EventTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/event/EventTest.java new file mode 100644 index 000000000..95baec828 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/event/EventTest.java @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.event; + +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.integration.repository.data.Employee; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.events.EventType; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.rocksdb.RocksDBModule; +import org.dizitart.no2.integration.repository.data.Employee; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.awaitility.Awaitility.await; +import static org.dizitart.no2.filters.Filter.ALL; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +@RunWith(Parameterized.class) +public class EventTest { + @Parameterized.Parameter + public boolean isProtected = false; + + private final String fileName = getRandomTempDbFile(); + + private Nitrite db; + private ObjectRepository employeeRepository; + private SampleListenerCollection listener; + + @Rule + public Retry retry = new Retry(3); + @Parameterized.Parameters(name = "Protected = {0}") + public static Collection data() { + return Arrays.asList(new Object[][]{ + {false}, + {true}, + }); + } + + @Before + public void setUp() { + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(fileName) + .build(); + + if (isProtected) { + db = Nitrite.builder() + .fieldSeparator(".") + .loadModule(storeModule) + .openOrCreate("test-user", "test-password"); + } else { + db = Nitrite.builder() + .fieldSeparator(".") + .loadModule(storeModule) + .openOrCreate(); + } + + employeeRepository = db.getRepository(Employee.class); + listener = new SampleListenerCollection(); + employeeRepository.subscribe(listener); + } + + @Test + public void testInsert() { + Employee employee = new Employee(); + employee.setEmpId(1L); + employeeRepository.insert(employee); + await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); + assertEquals(listener.getAction(), EventType.Insert); + assertNotNull(listener.getItem()); + } + + @Test + public void testUpdate() { + Employee e = new Employee(); + e.setEmpId(1L); + e.setAddress("abcd"); + employeeRepository.insert(e); + await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); + assertEquals(listener.getAction(), EventType.Insert); + assertNotNull(listener.getItem()); + + e.setAddress("xyz"); + employeeRepository.update(where("empId").eq(1L), e); + await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Update)); + assertEquals(listener.getAction(), EventType.Update); + assertNotNull(listener.getItem()); + + Employee byId = employeeRepository.getById(1L); + assertEquals(byId.getAddress(), "xyz"); + } + + @Test + public void testUpsert() { + Employee e = new Employee(); + e.setEmpId(1L); + e.setAddress("abcd"); + + employeeRepository.update(where("empId").eq(1), e, true); + await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); + assertEquals(listener.getAction(), EventType.Insert); + assertNotNull(listener.getItem()); + } + + @Test + public void testDelete() { + Employee e = new Employee(); + e.setEmpId(1L); + e.setAddress("abcd"); + + employeeRepository.insert(e); + await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); + + employeeRepository.remove(where("empId").eq(1L)); + await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Remove)); + + System.out.println("Action - " + listener.getAction()); + assertEquals(listener.getAction(), EventType.Remove); + assertNotNull(listener.getItem()); + } + + @Test + public void testDrop() { + employeeRepository.drop(); + assertNull(listener.getItem()); + } + + @Test + public void testClose() { + if (employeeRepository.isOpen()) { + employeeRepository.close(); + } + assertNull(listener.getItem()); + } + + @Test + public void testDeregister() { + employeeRepository.unsubscribe(listener); + Employee e = new Employee(); + e.setEmpId(1L); + e.setAddress("abcd"); + + employeeRepository.insert(e); + assertNull(listener.getAction()); + assertNull(listener.getItem()); + } + + @Test + public void testMultipleListeners() { + final AtomicInteger count = new AtomicInteger(0); + employeeRepository.subscribe(changeInfo -> count.incrementAndGet()); + + employeeRepository.subscribe(changeInfo -> count.incrementAndGet()); + + Employee e = new Employee(); + e.setEmpId(1L); + e.setAddress("abcd"); + employeeRepository.insert(e); + + await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); + assertEquals(count.get(), 2); + } + + @Test + public void testSingleEventListener() { + final AtomicInteger count = new AtomicInteger(0); + employeeRepository.subscribe(changeInfo -> count.incrementAndGet()); + + employeeRepository = db.getRepository(Employee.class); + Employee e = new Employee(); + e.setEmpId(1L); + e.setAddress("abcd"); + employeeRepository.insert(e); + + await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); + assertEquals(count.get(), 1); + } + + @After + public void clear() throws IOException { + if (employeeRepository != null) { + if (!employeeRepository.isDropped() + && employeeRepository.isOpen()) { + employeeRepository.remove(ALL); + employeeRepository.unsubscribe(listener); + employeeRepository.close(); + } + } + + if (db != null) { + db.commit(); + db.close(); + } + + deleteDb(fileName); + } + + private Callable listenerPrepared(final EventType action) { + return () -> listener.getAction() == action; + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/event/SampleListenerCollection.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/event/SampleListenerCollection.java new file mode 100644 index 000000000..6297ecbc1 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/event/SampleListenerCollection.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.event; + +import lombok.Getter; +import org.dizitart.no2.collection.events.CollectionEventInfo; +import org.dizitart.no2.collection.events.CollectionEventListener; +import org.dizitart.no2.collection.events.EventType; + +/** + * @author Anindya Chatterjee. + */ +@Getter +class SampleListenerCollection implements CollectionEventListener { + private EventType action; + private Object item; + + @Override + public void onEvent(CollectionEventInfo eventInfo) { + if (eventInfo != null) { + this.action = eventInfo.getEventType(); + this.item = eventInfo.getItem(); + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/migrate/MigrationTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/migrate/MigrationTest.java new file mode 100644 index 000000000..cb6128ba7 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/migrate/MigrationTest.java @@ -0,0 +1,571 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.migrate; + +import com.github.javafaker.Faker; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.Constants; +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.exceptions.MigrationException; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.migration.Instructions; +import org.dizitart.no2.migration.Migration; +import org.dizitart.no2.migration.TypeConverter; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.rocksdb.RocksDBModule; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.util.UUID; + +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.integration.TestUtil.*; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class MigrationTest { + private final String dbPath = getRandomTempDbFile(); + private Nitrite db; + private Faker faker; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + db = createDb(dbPath); + faker = new Faker(); + } + + @After + public void cleanUp() { + if (!db.isClosed()) { + db.close(); + } + + deleteDb(dbPath); + } + + @Test + public void testRepositoryMigrate() { + ObjectRepository oldRepo = db.getRepository(OldClass.class, "demo1"); + for (int i = 0; i < 10; i++) { + OldClass old = new OldClass(); + old.setEmpId(String.valueOf(faker.number().randomNumber())); + old.setFirstName(faker.name().firstName()); + old.setLastName(faker.name().lastName()); + old.setUuid(UUID.randomUUID().toString()); + + OldClass.Literature literature = new OldClass.Literature(); + literature.setRatings((float) faker.number().randomDouble(2, 1, 5)); + literature.setText(faker.lorem().paragraph()); + old.setLiterature(literature); + + oldRepo.insert(old); + } + + db.close(); + + Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { + @Override + public void migrate(Instructions instruction) { + instruction.forDatabase() + .addPassword("test-user", "test-password"); + + instruction.forRepository(OldClass.class, "demo1") + .renameRepository("new", null) + .changeDataType("empId", (TypeConverter) Long::parseLong) + .changeIdField(Fields.withNames("uuid"), Fields.withNames("empId")) + .deleteField("uuid") + .renameField("lastName", "familyName") + .addField("fullName", document -> document.get("firstName", String.class) + " " + + document.get("familyName", String.class)) + .dropIndex("firstName") + .dropIndex("literature.text") + .changeDataType("literature.ratings", (TypeConverter) Math::round); + } + }; + + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(dbPath) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate("test-user", "test-password"); + + ObjectRepository newRepo = db.getRepository(NewClass.class); + assertEquals(newRepo.size(), 10); + assertTrue(db.listCollectionNames().isEmpty()); + assertTrue(db.listKeyedRepository().isEmpty()); + + assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 2); + } + + @Test + public void testCollectionMigrate() { + NitriteCollection collection = db.getCollection("test"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + document.put("bloodGroup", faker.name().bloodGroup()); + document.put("age", faker.number().randomDigit()); + + collection.insert(document); + } + + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "firstName"); + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "bloodGroup"); + db.close(); + + Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { + @Override + public void migrate(Instructions instruction) { + instruction.forDatabase() + .addPassword("test-user", "test-password"); + + instruction.forCollection("test") + .rename("testCollectionMigrate") + .deleteField("lastName"); + } + }; + + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(dbPath) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate("test-user", "test-password"); + + collection = db.getCollection("testCollectionMigrate"); + assertTrue(collection.hasIndex("firstName")); + assertEquals(collection.size(), 10); + assertEquals(db.listCollectionNames().size(), 1); + assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 2); + db.close(); + + migration = new Migration(2, 3) { + @Override + public void migrate(Instructions instructions) { + instructions.forDatabase() + .changePassword("test-user", "test-password", "password"); + + instructions.forCollection("testCollectionMigrate") + .dropIndex("firstName") + .deleteField("bloodGroup") + .addField("name", document -> faker.name().fullName()) + .addField("address") + .addField("vehicles", 1) + .renameField("age", "ageGroup") + .createIndex(IndexType.NON_UNIQUE, "ageGroup"); + } + }; + + storeModule = RocksDBModule.withConfig() + .filePath(dbPath) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(3) + .addMigrations(migration) + .openOrCreate("test-user", "password"); + + collection = db.getCollection("testCollectionMigrate"); + assertEquals(collection.size(), 10); + assertEquals(db.listCollectionNames().size(), 1); + assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 3); + + assertFalse(collection.hasIndex("firstName")); + assertTrue(collection.hasIndex("ageGroup")); + assertEquals(collection.find(where("age").notEq(null)).size(), 0); + } + + @Test(expected = MigrationException.class) + public void testOpenWithoutSchemaVersion() { + NitriteCollection collection = db.getCollection("test"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + + collection.insert(document); + } + db.close(); + + Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { + @Override + public void migrate(Instructions instruction) { + + instruction.forCollection("test") + .rename("testOpenWithoutSchemaVersion") + .deleteField("lastName"); + } + }; + + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(dbPath) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testOpenWithoutSchemaVersion"); + assertEquals(collection.size(), 10); + db.close(); + + storeModule = RocksDBModule.withConfig() + .filePath(dbPath) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .openOrCreate(); + + collection = db.getCollection("testOpenWithoutSchemaVersion"); + assertEquals(collection.size(), 10); + } + + @Test + public void testDescendingSchema() { + NitriteCollection collection = db.getCollection("test"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + + collection.insert(document); + } + db.close(); + + Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { + @Override + public void migrate(Instructions instruction) { + + instruction.forCollection("test") + .rename("testDescendingSchema") + .deleteField("lastName"); + } + }; + + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(dbPath) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testDescendingSchema"); + assertEquals(collection.size(), 10); + db.close(); + + migration = new Migration(2, Constants.INITIAL_SCHEMA_VERSION) { + @Override + public void migrate(Instructions instructions) { + + instructions.forCollection("testDescendingSchema") + .rename("test"); + } + }; + + storeModule = RocksDBModule.withConfig() + .filePath(dbPath) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(1) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + db.close(); + } + + @Test + public void testMigrationWithoutVersion() { + NitriteCollection collection = db.getCollection("test"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + + collection.insert(document); + } + db.close(); + + Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { + @Override + public void migrate(Instructions instruction) { + + instruction.forCollection("test") + .rename("testMigrationWithoutVersion") + .deleteField("lastName"); + } + }; + + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(dbPath) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testMigrationWithoutVersion"); + assertEquals(collection.size(), 0); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + db.close(); + } + + @Test + public void testWrongSchemaVersionNoMigration() { + NitriteCollection collection = db.getCollection("testWrongSchemaVersionNoMigration"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + + collection.insert(document); + } + db.close(); + + Migration migration = new Migration(1, 2) { + @Override + public void migrate(Instructions instruction) { + + instruction.forCollection("testWrongSchemaVersionNoMigration") + .rename("test") + .deleteField("lastName"); + } + }; + + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(dbPath) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testWrongSchemaVersionNoMigration"); + assertEquals(collection.size(), 0); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + db.close(); + + migration = new Migration(2, 3) { + @Override + public void migrate(Instructions instructions) { + instructions.forCollection("test") + .rename("testWrongSchemaVersionNoMigration"); + } + }; + + storeModule = RocksDBModule.withConfig() + .filePath(dbPath) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testWrongSchemaVersionNoMigration"); + assertEquals(collection.size(), 0); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + db.close(); + } + + @Test + public void testReOpenAfterMigration() { + NitriteCollection collection = db.getCollection("testReOpenAfterMigration"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + + collection.insert(document); + } + db.close(); + + Migration migration = new Migration(1, 2) { + @Override + public void migrate(Instructions instruction) { + + instruction.forCollection("testReOpenAfterMigration") + .rename("test") + .deleteField("lastName"); + } + }; + + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(dbPath) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testReOpenAfterMigration"); + assertEquals(collection.size(), 0); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + db.close(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration) + .openOrCreate(); + + collection = db.getCollection("testReOpenAfterMigration"); + assertEquals(collection.size(), 0); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + db.close(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .openOrCreate(); + + collection = db.getCollection("testReOpenAfterMigration"); + assertEquals(collection.size(), 0); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + } + + @Test + public void testMultipleMigrations() { + NitriteCollection collection = db.getCollection("testMultipleMigrations"); + for (int i = 0; i < 10; i++) { + Document document = Document.createDocument(); + document.put("firstName", faker.name().firstName()); + document.put("lastName", faker.name().lastName()); + + collection.insert(document); + } + db.close(); + + Migration migration1 = new Migration(1, 2) { + @Override + public void migrate(Instructions instruction) { + + instruction.forCollection("testMultipleMigrations") + .rename("test"); + } + }; + + Migration migration2 = new Migration(2, 3) { + @Override + public void migrate(Instructions instruction) { + instruction.forCollection("test") + .addField("fullName", "Dummy Name"); + } + }; + + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(dbPath) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(2) + .addMigrations(migration1, migration2) + .openOrCreate(); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + assertEquals(collection.find(where("fullName").eq("Dummy Name")).size(), 0); + db.close(); + + Migration migration3 = new Migration(3, 4) { + @Override + public void migrate(Instructions instruction) { + instruction.forCollection("test") + .addField("age", 10); + } + }; + + storeModule = RocksDBModule.withConfig() + .filePath(dbPath) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .schemaVersion(4) + .addMigrations(migration1, migration2, migration3) + .openOrCreate(); + + collection = db.getCollection("test"); + assertEquals(collection.size(), 10); + assertEquals(collection.find(where("fullName").eq("Dummy Name")).size(), 10); + assertEquals(collection.find(where("age").eq(10)).size(), 10); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/migrate/NewClass.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/migrate/NewClass.java new file mode 100644 index 000000000..56ef25c22 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/migrate/NewClass.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.migrate; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Entity; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +/** + * @author Anindya Chatterjee + */ +@Data +@Entity(value = "new", indices = { + @Index(value = "familyName", type = IndexType.NON_UNIQUE), + @Index(value = "fullName", type = IndexType.NON_UNIQUE), + @Index(value = "literature.ratings", type = IndexType.NON_UNIQUE), +}) +public class NewClass implements Mappable { + @Id + private Long empId; + private String firstName; + private String familyName; + private String fullName; + private Literature literature; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("empId", empId) + .put("firstName", firstName) + .put("familyName", familyName) + .put("fullName", fullName) + .put("literature", literature.write(mapper)); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + empId = document.get("empId", Long.class); + firstName = document.get("firstName", String.class); + familyName = document.get("familyName", String.class); + fullName = document.get("fullName", String.class); + + Document doc = document.get("literature", Document.class); + literature = new Literature(); + literature.read(mapper, doc); + } + + @Data + public static class Literature implements Mappable { + private String text; + private Integer ratings; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("text", text) + .put("ratings", ratings); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + text = document.get("text", String.class); + ratings = document.get("ratings", Integer.class); + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/migrate/OldClass.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/migrate/OldClass.java new file mode 100644 index 000000000..3bbb09b4e --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/migrate/OldClass.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.migrate; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Entity; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +/** + * @author Anindya Chatterjee + */ +@Data +@Entity(value = "old", indices = { + @Index(value = "firstName", type = IndexType.NON_UNIQUE), + @Index(value = "lastName", type = IndexType.NON_UNIQUE), + @Index(value = "literature.text", type = IndexType.FULL_TEXT), + @Index(value = "literature.ratings", type = IndexType.NON_UNIQUE), +}) +public class OldClass implements Mappable { + @Id + private String uuid; + private String empId; + private String firstName; + private String lastName; + private Literature literature; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("empId", empId) + .put("uuid", uuid) + .put("firstName", firstName) + .put("lastName", lastName) + .put("literature", literature.write(mapper)); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + empId = document.get("empId", String.class); + uuid = document.get("uuid", String.class); + firstName = document.get("firstName", String.class); + lastName = document.get("lastName", String.class); + + Document doc = document.get("literature", Document.class); + literature = new Literature(); + literature.read(mapper, doc); + } + + @Data + public static class Literature implements Mappable { + private String text; + private Float ratings; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("text", text) + .put("ratings", ratings); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + text = document.get("text", String.class); + ratings = document.get("ratings", Float.class); + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/BaseObjectRepositoryTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/BaseObjectRepositoryTest.java new file mode 100644 index 000000000..ae5716ff0 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/BaseObjectRepositoryTest.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteBuilder; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.integration.repository.data.*; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.rocksdb.RocksDBModule; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.Arrays; +import java.util.Collection; + +import static org.dizitart.no2.filters.Filter.ALL; +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; + +@RunWith(value = Parameterized.class) +public abstract class BaseObjectRepositoryTest { + @Parameterized.Parameter + public boolean isProtected = false; + + protected Nitrite db; + protected ObjectRepository companyRepository; + protected ObjectRepository employeeRepository; + protected ObjectRepository aObjectRepository; + protected ObjectRepository cObjectRepository; + protected ObjectRepository bookRepository; + + private final String fileName = getRandomTempDbFile(); + + @Rule + public Retry retry = new Retry(3); + @Parameterized.Parameters(name = "Protected = {0}") + public static Collection data() { + return Arrays.asList(new Object[][]{ + {false}, + {true}, + }); + } + + @Before + public void setUp() { + openDb(); + + companyRepository = db.getRepository(Company.class); + employeeRepository = db.getRepository(Employee.class); + + aObjectRepository = db.getRepository(ClassA.class); + cObjectRepository = db.getRepository(ClassC.class); + + bookRepository = db.getRepository(Book.class); + + for (int i = 0; i < 10; i++) { + Company company = DataGenerator.generateCompanyRecord(); + companyRepository.insert(company); + Employee employee = DataGenerator.generateEmployee(); + employee.setEmpId((long) i + 1); + employeeRepository.insert(employee); + + aObjectRepository.insert(ClassA.create(i + 50)); + cObjectRepository.insert(ClassC.create(i + 30)); + + Book book = DataGenerator.randomBook(); + bookRepository.insert(book); + } + } + + protected void openDb() { + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(fileName) + .build(); + + NitriteBuilder nitriteBuilder = Nitrite.builder() + .fieldSeparator(".") + .loadModule(storeModule); + + if (isProtected) { + db = nitriteBuilder.openOrCreate("test-user", "test-password"); + } else { + db = nitriteBuilder.openOrCreate(); + } + } + + @After + public void clear() throws Exception { + if (companyRepository != null && !companyRepository.isDropped()) { + companyRepository.remove(ALL); + } + + if (employeeRepository != null && !employeeRepository.isDropped()) { + employeeRepository.remove(ALL); + } + + if (aObjectRepository != null && !aObjectRepository.isDropped()) { + aObjectRepository.remove(ALL); + } + + if (cObjectRepository != null && !cObjectRepository.isDropped()) { + cObjectRepository.remove(ALL); + } + + if (bookRepository != null && !bookRepository.isDropped()) { + bookRepository.remove(ALL); + } + + if (db != null && !db.isClosed()) { + db.commit(); + db.close(); + } + + deleteDb(fileName); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/CustomFieldSeparatorTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/CustomFieldSeparatorTest.java new file mode 100644 index 000000000..a89c10612 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/CustomFieldSeparatorTest.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.integration.repository.data.Company; +import org.dizitart.no2.integration.repository.data.Note; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; +import org.dizitart.no2.repository.annotations.Indices; +import org.dizitart.no2.rocksdb.RocksDBModule; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.Serializable; +import java.util.Date; + +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee + */ +public class CustomFieldSeparatorTest { + private final String fileName = getRandomTempDbFile(); + private ObjectRepository repository; + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(fileName) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(":") + .openOrCreate(); + + repository = db.getRepository(EmployeeForCustomSeparator.class); + } + + @After + public void reset() { + (new NitriteConfig()).fieldSeparator("."); + if (db != null && !db.isClosed()) { + db.close(); + deleteDb(fileName); + } + } + + @Test + public void testFieldSeparator() { + assertEquals(NitriteConfig.getFieldSeparator(), ":"); + } + + @Test + public void testFindByEmbeddedField() { + EmployeeForCustomSeparator employee = new EmployeeForCustomSeparator(); + employee.setCompany(new Company()); + employee.setEmployeeNote(new Note()); + + employee.setEmpId(123L); + employee.setJoinDate(new Date()); + employee.setBlob(new byte[0]); + employee.setAddress("Dummy address"); + + employee.getCompany().setCompanyId(987L); + employee.getCompany().setCompanyName("Dummy Company"); + employee.getCompany().setDateCreated(new Date()); + + employee.getEmployeeNote().setNoteId(567L); + employee.getEmployeeNote().setText("Dummy Note"); + + repository.insert(employee); + + assertEquals(repository.find(where("employeeNote.text").eq("Dummy Note")).size(), 0); + assertEquals(repository.find(where("employeeNote:text").text("Dummy Note")).size(), 1); + + assertEquals(repository.find(where("company.companyName").eq("Dummy Company")).size(), 0); + assertEquals(repository.find(where("company:companyName").eq("Dummy Company")).size(), 1); + } + + @ToString + @EqualsAndHashCode + @Indices({ + @Index(value = "joinDate", type = IndexType.NON_UNIQUE), + @Index(value = "address", type = IndexType.FULL_TEXT), + @Index(value = "employeeNote:text", type = IndexType.FULL_TEXT) + }) + public static class EmployeeForCustomSeparator implements Serializable, Mappable { + @Id + @Getter + @Setter + private Long empId; + + @Getter + @Setter + private Date joinDate; + + @Getter + @Setter + private String address; + + @Getter + @Setter + private Company company; + + @Getter + @Setter + private byte[] blob; + + @Getter + @Setter + private Note employeeNote; + + EmployeeForCustomSeparator() { + } + + public EmployeeForCustomSeparator(EmployeeForCustomSeparator copy) { + empId = copy.empId; + joinDate = copy.joinDate; + address = copy.address; + company = copy.company; + blob = copy.blob; + employeeNote = copy.employeeNote; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument().put("empId", empId) + .put("joinDate", joinDate) + .put("address", address) + .put("blob", blob) + .put("company", company.write(mapper)) + .put("employeeNote", employeeNote.write(mapper)); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + empId = document.get("empId", Long.class); + joinDate = document.get("joinDate", Date.class); + address = document.get("address", String.class); + blob = document.get("blob", byte[].class); + employeeNote = new Note(); + Document doc = document.get("employeeNote", Document.class); + employeeNote.read(mapper, doc); + company = new Company(); + doc = document.get("company", Document.class); + company.read(mapper, doc); + } + } + +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/FieldProcessorTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/FieldProcessorTest.java new file mode 100644 index 000000000..73a093082 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/FieldProcessorTest.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.integration.repository.data.EncryptedPerson; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.common.crypto.AESEncryptor; +import org.dizitart.no2.common.crypto.Encryptor; +import org.dizitart.no2.common.processors.Processor; +import org.dizitart.no2.common.processors.StringFieldEncryptionProcessor; +import org.dizitart.no2.exceptions.NitriteSecurityException; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.store.NitriteMap; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.nio.charset.StandardCharsets; +import java.util.Date; +import java.util.List; + +import static org.dizitart.no2.common.util.Iterables.toList; +import static org.dizitart.no2.common.util.ObjectUtils.findRepositoryName; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class FieldProcessorTest extends BaseObjectRepositoryTest { + private ObjectRepository persons; + private StringFieldEncryptionProcessor fieldProcessor; + + @Before + public void setUp() { + super.setUp(); + persons = db.getRepository(EncryptedPerson.class); + fieldProcessor = new StringFieldEncryptionProcessor("s3k4e8"); + fieldProcessor.addFields("creditCardNumber", "cvv"); + + EncryptedPerson person = new EncryptedPerson(); + person.setName("John Doe"); + person.setCreditCardNumber("5548960345687452"); + person.setCvv("007"); + person.setExpiryDate(new Date()); + + persons.insert(person); + + persons.addProcessor(fieldProcessor); + + person = new EncryptedPerson(); + person.setName("Jane Doe"); + person.setCreditCardNumber("5500960345687452"); + person.setCvv("008"); + person.setExpiryDate(new Date()); + persons.insert(person); + } + + @Test + public void testFieldEncryptionInNitriteMap() { + NitriteMap nitriteMap = persons.getDocumentCollection().getStore() + .openMap(findRepositoryName(EncryptedPerson.class, null), NitriteId.class, Document.class); + + List documents = toList(nitriteMap.values()); + for (Document document : documents) { + if (document.get("creditCardNumber", String.class).equalsIgnoreCase("5548960345687452")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("creditCardNumber", String.class).equalsIgnoreCase("5500960345687452")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("cvv", String.class).equalsIgnoreCase("008")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("cvv", String.class).equalsIgnoreCase("007")) { + Assert.fail("unencrypted secret text found"); + } + } + } + + @Test + public void testSuccessfulDecryption() { + EncryptedPerson person = persons.find(where("name").eq("Jane Doe")).firstOrNull(); + assertNotNull(person); + + assertEquals(person.getCreditCardNumber(), "5500960345687452"); + assertEquals(person.getCvv(), "008"); + + person = persons.find(where("name").eq("John Doe")).firstOrNull(); + assertNotNull(person); + + assertEquals(person.getCreditCardNumber(), "5548960345687452"); + assertEquals(person.getCvv(), "007"); + } + + @Test(expected = NitriteSecurityException.class) + public void testFailedDecryption() { + ObjectRepository testPersons = db.getRepository(EncryptedPerson.class, "test"); + + Encryptor encryptor = new AESEncryptor("secret"); + Encryptor wrongEncryptor = new AESEncryptor("secret", "AES/GCM/NoPadding", + 5, 5, 5); + + testPersons.addProcessor(new Processor() { + @Override + public Document processBeforeWrite(Document document) { + String creditCardNumber = document.get("creditCardNumber", String.class); + String encryptedCreditCardNumber = encryptor.encrypt(creditCardNumber.getBytes(StandardCharsets.UTF_8)); + document.put("creditCardNumber", encryptedCreditCardNumber); + return document; + } + + @Override + public Document processAfterRead(Document document) { + String encryptedCreditCardNumber = document.get("creditCardNumber", String.class); + String creditCardNumber = wrongEncryptor.decrypt(encryptedCreditCardNumber); + document.put("creditCardNumber", creditCardNumber); + return document; + } + }); + + EncryptedPerson person = new EncryptedPerson(); + person.setName("John Doe"); + person.setCreditCardNumber("5548960345687452"); + person.setCvv("007"); + person.setExpiryDate(new Date()); + + testPersons.insert(person); + + person = new EncryptedPerson(); + person.setName("Jane Doe"); + person.setCreditCardNumber("5500960345687452"); + person.setCvv("008"); + person.setExpiryDate(new Date()); + testPersons.insert(person); + + testPersons.find(where("name").eq("Jane Doe")).firstOrNull(); + } + + @Test + public void testSearchOnEncryptedField() { + EncryptedPerson person = persons.find(where("cvv").eq("008")).firstOrNull(); + assertNull(person); + } + + @Test + public void testUpdateEncryptedField() { + EncryptedPerson person = new EncryptedPerson(); + person.setName("John Doe"); + person.setCreditCardNumber("00000000000000"); + person.setCvv("007"); + person.setExpiryDate(new Date()); + + WriteResult writeResult = persons.update(where("name").eq("John Doe"), person); + assertEquals(writeResult.getAffectedCount(), 1); + + person = persons.find(where("name").eq("John Doe")).firstOrNull(); + assertNotNull(person); + + assertEquals(person.getCreditCardNumber(), "00000000000000"); + assertEquals(person.getCvv(), "007"); + } + + @Test + public void testIndexOnEncryptedField() { + persons.createIndex("cvv"); + EncryptedPerson person = persons.find(where("cvv").eq("008")).firstOrNull(); + assertNull(person); + } + + @Test + public void testRemoveProcessor() { + EncryptedPerson person = persons.find(where("cvv").eq("008")).firstOrNull(); + assertNull(person); + + person = persons.find(where("creditCardNumber").eq("5548960345687452")).firstOrNull(); + assertNull(person); + + persons.removeProcessor(fieldProcessor); + + person = persons.find(where("cvv").eq("008")).firstOrNull(); + assertNotNull(person); + + person = persons.find(where("creditCardNumber").eq("5548960345687452")).firstOrNull(); + assertNotNull(person); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/InternalClass.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/InternalClass.java new file mode 100644 index 000000000..1a52708ce --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/InternalClass.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Data +class InternalClass implements Mappable { + @Id + private long id; + private String name; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("id", id) + .put("name", name); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Long.class); + name = document.get("name", String.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/NitriteIdAsIdTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/NitriteIdAsIdTest.java new file mode 100644 index 000000000..dedd5e256 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/NitriteIdAsIdTest.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.integration.repository.data.WithNitriteId; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.common.util.Iterables; +import org.dizitart.no2.exceptions.InvalidIdException; +import org.dizitart.no2.integration.TestUtil; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.IOException; + +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * @author Anindya Chatterjee + */ +public class NitriteIdAsIdTest { + private final String fileName = getRandomTempDbFile(); + private Nitrite db; + private ObjectRepository repo; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void before() { + db = TestUtil.createDb(fileName); + repo = db.getRepository(WithNitriteId.class); + } + + @After + public void after() throws IOException { + db.close(); + deleteDb(fileName); + } + + @Test + public void testNitriteIdField() { + WithNitriteId item1 = new WithNitriteId(); + item1.name = "first"; + + WithNitriteId item2 = new WithNitriteId(); + item2.name = "second"; + + repo.insert(item1, item2); + + Cursor cursor = repo.find(); + for (WithNitriteId withNitriteId : cursor) { + System.out.println(withNitriteId.name); + assertNotNull(withNitriteId.idField); + } + + WithNitriteId withNitriteId = cursor.firstOrNull(); + withNitriteId.name = "third"; + + NitriteId id = withNitriteId.idField; + repo.update(withNitriteId); + + WithNitriteId byId = repo.getById(id); + assertEquals(withNitriteId, byId); + assertEquals(repo.size(), 2); + } + + @Test(expected = InvalidIdException.class) + public void setIdDuringInsert() { + WithNitriteId item1 = new WithNitriteId(); + item1.name = "first"; + item1.idField = NitriteId.newId(); + + repo.insert(item1); + } + + @Test + public void changeIdDuringUpdate() { + WithNitriteId item2 = new WithNitriteId(); + item2.name = "second"; + WriteResult result = repo.insert(item2); + NitriteId nitriteId = Iterables.firstOrNull(result); + WithNitriteId byId = repo.getById(nitriteId); + byId.idField = NitriteId.newId(); + + result = repo.update(byId); + assertEquals(result.getAffectedCount(), 0); + assertEquals(repo.size(), 1); + } + +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/ObjectCursorTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/ObjectCursorTest.java new file mode 100644 index 000000000..5be20ded7 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/ObjectCursorTest.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.integration.repository.data.Employee; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.repository.Cursor; +import org.junit.Test; + +import java.util.AbstractCollection; + +/** + * @author Anindya Chatterjee + */ +public class ObjectCursorTest extends BaseObjectRepositoryTest { + + @Test(expected = ValidationException.class) + public void testProjectForInterface() { + Cursor cursor = employeeRepository.find(); + cursor.project(Comparable.class); + } + + @Test(expected = ValidationException.class) + public void testProjectForPrimitive() { + Cursor cursor = employeeRepository.find(); + cursor.project(int.class); + } + + @Test(expected = ValidationException.class) + public void testProjectForArray() { + Cursor cursor = employeeRepository.find(); + cursor.project(String[].class); + } + + @Test(expected = ValidationException.class) + public void testProjectForAbstractClass() { + Cursor cursor = employeeRepository.find(); + cursor.project(AbstractCollection.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryNegativeTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryNegativeTest.java new file mode 100644 index 000000000..e070d485d --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryNegativeTest.java @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.integration.repository.data.*; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.exceptions.*; +import org.dizitart.no2.integration.TestUtil; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.IOException; + +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class ObjectRepositoryNegativeTest { + private final String dbPath = getRandomTempDbFile(); + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + db = TestUtil.createDb(dbPath); + } + + @After + public void close() throws IOException { + db.close(); + db = null; + deleteDb(dbPath); + } + + @Test(expected = ObjectMappingException.class) + public void testWithCircularReference() { + ObjectRepository repository = db.getRepository(WithCircularReference.class); + + WithCircularReference parent = new WithCircularReference(); + parent.setName("parent"); + WithCircularReference object = new WithCircularReference(); + object.setName("test"); + object.setParent(parent); + // circular reference + parent.setParent(object); + + WriteResult result = repository.insert(object); + for (NitriteId id : result) { + WithCircularReference instance = repository.getById(id); + assertEquals(instance.getName(), object.getName()); + assertEquals(instance.getParent().getName(), object.getParent().getName()); + } + } + + @Test(expected = ObjectMappingException.class) + public void testWithCustomConstructor() { + ObjectRepository repository = db.getRepository(WithCustomConstructor.class); + + WithCustomConstructor object = new WithCustomConstructor("test", 2L); + + WriteResult result = repository.insert(object); + for (NitriteId id : result) { + WithCustomConstructor instance = repository.getById(id); + assertEquals(object.getName(), instance.getName()); + assertEquals(object.getNumber(), instance.getNumber()); + } + } + + @Test(expected = InvalidIdException.class) + public void testWithEmptyStringId() { + ObjectRepository repository = db.getRepository(WithEmptyStringId.class); + WithEmptyStringId object = new WithEmptyStringId(); + object.setName(""); // empty id value + + WriteResult result = repository.insert(object); + for (NitriteId id : result) { + WithEmptyStringId instance = repository.getById(id); + assertEquals(instance, object); + } + } + + @Test(expected = InvalidIdException.class) + public void testWithNullId() { + ObjectRepository repository = db.getRepository(WithNullId.class); + WithNullId object = new WithNullId(); + + WriteResult result = repository.insert(object); + for (NitriteId id : result) { + WithNullId instance = repository.getById(id); + assertEquals(instance, object); + } + } + + @Test(expected = ValidationException.class) + public void testWithValueTypeRepository() { + ObjectRepository repository = db.getRepository(String.class); + repository.insert("test"); + } + + @Test(expected = InvalidOperationException.class) + public void testFindResultRemove() { + ObjectRepository repository = db.getRepository(Employee.class); + repository.insert(DataGenerator.generateEmployee()); + RecordStream result = repository.find(); + result.iterator().remove(); + } + + @Test(expected = IndexingException.class) + public void testWithObjectId() { + ObjectRepository repository = db.getRepository(WithObjectId.class); + WithOutId id = new WithOutId(); + id.setName("test"); + id.setNumber(1); + + WithObjectId object = new WithObjectId(); + object.setWithOutId(id); + repository.insert(object); + } + + @Test(expected = NotIdentifiableException.class) + public void testUpdateNoId() { + ObjectRepository repository = db.getRepository(WithOutId.class); + WithOutId object = new WithOutId(); + object.setName("name"); + object.setNumber(1L); + repository.update(object); + } + + @Test(expected = NotIdentifiableException.class) + public void testRemoveNoId() { + ObjectRepository repository = db.getRepository(WithOutId.class); + WithOutId object = new WithOutId(); + object.setName("name"); + object.setNumber(1L); + repository.remove(object); + } + + @Test(expected = ValidationException.class) + public void testProjectionFailedInstantiate() { + ObjectRepository repository = db.getRepository(WithOutId.class); + WithOutId object = new WithOutId(); + object.setName("name"); + object.setNumber(1L); + repository.insert(object); + + RecordStream project = repository.find().project(NitriteId.class); + assertNull(project.toList()); + } + + @Test(expected = ValidationException.class) + public void testNullInsert() { + ObjectRepository repository = db.getRepository(WithOutId.class); + repository.insert(null); + } + + @Test(expected = InvalidIdException.class) + public void testGetByNullId() { + ObjectRepository repository = db.getRepository(WithPublicField.class); + WithPublicField object = new WithPublicField(); + object.name = "test"; + object.number = 2; + + repository.insert(object); + WithPublicField instance = repository.getById(null); + assertEquals(object.name, instance.name); + assertEquals(object.number, instance.number); + } + + @Test + public void testExternalNitriteId() { + ObjectRepository repository = db.getRepository(WithNitriteId.class); + WithNitriteId obj = new WithNitriteId(); + NitriteId id = NitriteId.createId("1"); + obj.setIdField(id); + obj.setName("testExternalNitriteId"); + WriteResult result = repository.update(obj, true); + + obj = new WithNitriteId(); + id = result.iterator().next(); + obj.setIdField(id); + obj.setName("testExternalNitriteId"); + result = repository.update(obj, true); + assertNotEquals(id.getIdValue(), result.iterator().next().getIdValue()); + } + + @Test(expected = IndexingException.class) + public void testWithoutEmbeddedId() { + ObjectRepository repository = db.getRepository(WithoutEmbeddedId.class); + assertNull(repository); + } + + @Test(expected = InvalidIdException.class) + public void testGetByWrongIdType() { + ObjectRepository repository = db.getRepository(WithPublicField.class); + WithPublicField object = new WithPublicField(); + object.name = "test"; + object.number = 2; + + repository.insert(object); + + NitriteId id = NitriteId.createId("1"); + WithPublicField instance = repository.getById(id); + assertEquals(object.name, instance.name); + assertEquals(object.number, instance.number); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryTest.java new file mode 100644 index 000000000..4fd11a005 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryTest.java @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import com.github.javafaker.Faker; +import lombok.Data; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.meta.Attributes; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.MappableMapper; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.integration.repository.data.*; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Entity; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; +import org.dizitart.no2.rocksdb.RocksDBModule; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.IOException; +import java.util.Date; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.awaitility.Awaitility.await; +import static org.dizitart.no2.common.module.NitriteModule.module; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class ObjectRepositoryTest { + private final String dbPath = getRandomTempDbFile(); + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + NitriteMapper mapper = new MappableMapper(); + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(dbPath) + .build(); + + db = Nitrite.builder() + .loadModule(module(mapper)) + .loadModule(storeModule) + .fieldSeparator(".") + .openOrCreate(); + } + + @After + public void close() throws IOException { + db.close(); + db = null; + deleteDb(dbPath); + } + + @Test + public void testWithClassField() { + ObjectRepository repository = db.getRepository(WithClassField.class); + + WithClassField object = new WithClassField(); + object.setName("test"); + object.setClazz(String.class); + + repository.insert(object); + WithClassField instance = repository.getById("test"); + assertEquals(instance.getName(), object.getName()); + assertEquals(instance.getClazz(), object.getClazz()); + } + + @Test + public void testWithFinalField() { + ObjectRepository repository = db.getRepository(WithFinalField.class); + WithFinalField object = new WithFinalField(); + object.setName("test"); + + repository.insert(object); + for (WithFinalField instance : repository.find()) { + assertEquals(object.getName(), instance.getName()); + assertEquals(object.getNumber(), instance.getNumber()); + } + } + + @Test + public void testWithOutGetterSetter() { + ObjectRepository repository = db.getRepository(WithOutGetterSetter.class); + WithOutGetterSetter object = new WithOutGetterSetter(); + + repository.insert(object); + for (WithOutGetterSetter instance : repository.find()) { + assertEquals(object, instance); + } + } + + @Test + public void testWithOutId() { + ObjectRepository repository = db.getRepository(WithOutId.class); + WithOutId object = new WithOutId(); + object.setName("test"); + object.setNumber(2); + + repository.insert(object); + for (WithOutId instance : repository.find()) { + assertEquals(object.getName(), instance.getName()); + assertEquals(object.getNumber(), instance.getNumber()); + } + } + + @Test + public void testWithPublicField() { + ObjectRepository repository = db.getRepository(WithPublicField.class); + WithPublicField object = new WithPublicField(); + object.name = "test"; + object.number = 2; + + repository.insert(object); + WithPublicField instance = repository.getById("test"); + assertEquals(object.name, instance.name); + assertEquals(object.number, instance.number); + } + + @Test + public void testWithTransientField() { + ObjectRepository repository = db.getRepository(WithTransientField.class); + WithTransientField object = new WithTransientField(); + object.setNumber(2); + object.setName("test"); + + repository.insert(object); + WithTransientField instance = repository.getById(2L); + assertNotEquals(object.getName(), instance.getName()); + assertNull(instance.getName()); + assertEquals(object.getNumber(), instance.getNumber()); + } + + @Test + public void testWriteThousandRecords() { + int count = 5000; + + ObjectRepository repository = db.getRepository(StressRecord.class); + + for (int i = 0; i < count; i++) { + StressRecord record = new StressRecord(); + record.setFirstName(UUID.randomUUID().toString()); + record.setFailed(false); + record.setLastName(UUID.randomUUID().toString()); + record.setProcessed(false); + + repository.insert(record); + } + + Cursor cursor + = repository.find(where("failed").eq(false)); + + for (StressRecord record : cursor) { + record.setProcessed(true); + repository.update(where("firstName").eq(record.getFirstName()), record); + } + } + + @Test + public void testWithPackagePrivateClass() { + ObjectRepository repository = db.getRepository(InternalClass.class); + InternalClass internalClass = new InternalClass(); + internalClass.setId(1); + internalClass.setName("name"); + + repository.insert(internalClass); + InternalClass instance = repository.getById((long) 1); + assertEquals(internalClass.getName(), instance.getName()); + assertEquals(internalClass.getId(), instance.getId()); + } + + @Test + public void testWithPrivateConstructor() { + ObjectRepository repository = + db.getRepository(WithPrivateConstructor.class); + + WithPrivateConstructor object = WithPrivateConstructor.create("test", 2L); + repository.insert(object); + for (WithPrivateConstructor instance : repository.find()) { + assertEquals(object, instance); + } + } + + @Test + public void testWithDateAsId() { + ObjectRepository repository = db.getRepository(WithDateId.class); + + WithDateId object1 = new WithDateId(); + object1.setId(new Date(1482773634L)); + object1.setName("first date"); + repository.insert(object1); + + WithDateId object2 = new WithDateId(); + object2.setName("second date"); + object2.setId(new Date(1482773720L)); + repository.insert(object2); + + assertEquals(repository.find(where("id").eq(new Date(1482773634L))) + .firstOrNull(), object1); + assertEquals(repository.find(where("id").eq(new Date(1482773720L))) + .firstOrNull(), object2); + } + + @Test + public void testWithIdInheritance() { + ObjectRepository repository = db.getRepository(ChildClass.class); + assertTrue(repository.hasIndex("id")); + assertTrue(repository.hasIndex("date")); + assertTrue(repository.hasIndex("text")); + + ChildClass childClass = new ChildClass(); + childClass.setName("first"); + childClass.setDate(new Date(100000L)); + childClass.setId(1L); + childClass.setText("I am first class"); + repository.insert(childClass); + + childClass = new ChildClass(); + childClass.setName("seconds"); + childClass.setDate(new Date(100001L)); + childClass.setId(2L); + childClass.setText("I am second class"); + repository.insert(childClass); + + childClass = new ChildClass(); + childClass.setName("third"); + childClass.setDate(new Date(100002L)); + childClass.setId(3L); + childClass.setText("I am third class"); + repository.insert(childClass); + + assertEquals(repository.find(where("text").text("class")).size(), 3); + assertEquals(repository.find(where("text").text("second")).size(), 0); // filtered in stop words + assertEquals(repository.find(where("date").eq(new Date(100000L))).size(), 1); + assertEquals(repository.find(where("id").eq(1L)).size(), 1); + } + + @Test + public void testAttributes() { + ObjectRepository repository = db.getRepository(WithDateId.class); + Attributes attributes = new Attributes(repository.getDocumentCollection().getName()); + repository.setAttributes(attributes); + assertEquals(repository.getAttributes(), attributes); + } + + @Test + public void testKeyedRepository() { + // an object repository of employees who are managers + ObjectRepository managerRepo = db.getRepository(Employee.class, "managers"); + + // an object repository of all employee + ObjectRepository employeeRepo = db.getRepository(Employee.class); + + // and object repository of employees who are developers + ObjectRepository developerRepo = db.getRepository(Employee.class, "developers"); + + Employee manager = new Employee(); + manager.setEmpId(1L); + manager.setAddress("abcd"); + manager.setJoinDate(new Date()); + + Employee developer = new Employee(); + developer.setEmpId(2L); + developer.setAddress("xyz"); + developer.setJoinDate(new Date()); + + managerRepo.insert(manager); + employeeRepo.insert(manager, developer); + developerRepo.insert(developer); + + assertTrue(db.hasRepository(Employee.class)); + assertTrue(db.hasRepository(Employee.class, "managers")); + assertTrue(db.hasRepository(Employee.class, "developers")); + + assertEquals(db.listRepositories().size(), 1); + assertEquals(db.listKeyedRepository().size(), 2); + + assertEquals(employeeRepo.find(where("address").text("abcd")).size(), 1); + assertEquals(employeeRepo.find(where("address").text("xyz")).size(), 1); + assertEquals(managerRepo.find(where("address").text("xyz")).size(), 0); + assertEquals(managerRepo.find(where("address").text("abcd")).size(), 1); + assertEquals(developerRepo.find(where("address").text("xyz")).size(), 1); + assertEquals(developerRepo.find(where("address").text("abcd")).size(), 0); + } + + @Test + public void testEntityRepository() { + ObjectRepository managerRepo = db.getRepository(EmployeeEntity.class, "managers"); + ObjectRepository employeeRepo = db.getRepository(EmployeeEntity.class); + ObjectRepository developerRepo = db.getRepository(EmployeeEntity.class, "developers"); + + managerRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); + employeeRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); + developerRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); + + boolean errored = false; + try { + NitriteCollection collection = db.getCollection("entity.employee"); + } catch (ValidationException e) { + errored = true; + } + assertTrue(errored); + + assertTrue(db.listRepositories().contains("entity.employee")); + assertEquals(db.listKeyedRepository().size(), 2); + assertEquals(db.listCollectionNames().size(), 0); + + assertTrue(managerRepo.hasIndex("firstName")); + assertTrue(managerRepo.hasIndex("lastName")); + assertTrue(employeeRepo.hasIndex("lastName")); + assertTrue(employeeRepo.hasIndex("lastName")); + + managerRepo.drop(); + assertEquals(db.listKeyedRepository().size(), 1); + } + + @Test + public void testIssue217() { + ObjectRepository employeeRepo = db.getRepository(EmployeeEntity.class); + AtomicInteger counter = new AtomicInteger(0); + employeeRepo.subscribe(eventInfo -> counter.incrementAndGet()); + + ObjectRepository employeeRepo2 = db.getRepository(EmployeeEntity.class); + employeeRepo2.insert(new EmployeeEntity()); + await().atMost(5, TimeUnit.SECONDS).until(() -> counter.get() == 1); + } + + @Data + @Entity(value = "entity.employee", indices = { + @Index(value = "firstName", type = IndexType.NON_UNIQUE), + @Index(value = "lastName", type = IndexType.NON_UNIQUE), + }) + private static class EmployeeEntity implements Mappable { + private static final Faker faker = new Faker(); + + @Id + private Long id; + private String firstName; + private String lastName; + + public EmployeeEntity() { + id = faker.number().randomNumber(); + firstName = faker.name().firstName(); + lastName = faker.name().lastName(); + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("id", id) + .put("firstName", firstName) + .put("lastName", lastName); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Long.class); + firstName = document.get("firstName", String.class); + lastName = document.get("lastName", String.class); + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/ProjectionTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/ProjectionTest.java new file mode 100644 index 000000000..c6a85b0a3 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/ProjectionTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.integration.repository.data.SubEmployee; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.junit.Test; + +import java.util.Iterator; + +import static org.dizitart.no2.collection.FindOptions.skipBy; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class ProjectionTest extends BaseObjectRepositoryTest { + + @Test + public void testHasMore() { + RecordStream iterable = employeeRepository.find(skipBy(0).limit(5)) + .project(SubEmployee.class); + assertFalse(iterable.isEmpty()); + } + + @Test + public void testSize() { + RecordStream iterable = employeeRepository.find(skipBy(0).limit(5)) + .project(SubEmployee.class); + assertEquals(iterable.size(), 5); + } + + @Test + public void testToString() { + RecordStream iterable = employeeRepository.find(skipBy(0).limit(5)) + .project(SubEmployee.class); + assertNotNull(iterable.toString()); + } + + @Test(expected = InvalidOperationException.class) + public void testRemove() { + RecordStream iterable = employeeRepository.find(skipBy(0).limit(5)) + .project(SubEmployee.class); + Iterator iterator = iterable.iterator(); + if (iterator.hasNext()) { + iterator.next(); + iterator.remove(); + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryCompoundIndexTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryCompoundIndexTest.java new file mode 100644 index 000000000..9431d991e --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryCompoundIndexTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.integration.repository.data.Book; +import org.dizitart.no2.integration.repository.data.BookId; +import org.junit.Test; + +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee + */ +public class RepositoryCompoundIndexTest extends BaseObjectRepositoryTest { + + @Test + public void testFindById() { + BookId bookId = new BookId(); + bookId.setAuthor("John Doe"); + bookId.setIsbn("123456"); + bookId.setName("Nitrite Database"); + + Book book = new Book(); + book.setBookId(bookId); + book.setDescription("Some random book description"); + book.setPrice(22.56); + book.setPublisher("My Publisher House"); + book.setTags(Arrays.asList("database", "nosql")); + + bookRepository.insert(book); + + Book bookById = bookRepository.getById(bookId); + assertEquals(bookById, book); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryFactoryTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryFactoryTest.java new file mode 100644 index 000000000..3c89260ac --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryFactoryTest.java @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.*; +import org.dizitart.no2.collection.events.CollectionEventListener; +import org.dizitart.no2.collection.meta.Attributes; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.common.concurrent.LockService; +import org.dizitart.no2.common.processors.Processor; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.integration.TestUtil; +import org.dizitart.no2.repository.RepositoryFactory; +import org.dizitart.no2.store.NitriteStore; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.util.Collection; + +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.assertNotNull; + +/** + * @author Anindya Chatterjee + */ +public class RepositoryFactoryTest { + private Nitrite db; + private final String fileName = getRandomTempDbFile(); + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + db = TestUtil.createDb(fileName); + } + + @Test + public void testRepositoryFactory() { + RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); + assertNotNull(factory); + } + + @Test(expected = ValidationException.class) + public void testNullType() { + RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); + factory.getRepository(db.getConfig(), null, "dummy"); + } + + @Test + public void testNullCollection() { + RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); + factory.getRepository(db.getConfig(), DummyCollection.class, null); + } + + @Test(expected = ValidationException.class) + public void testNullContext() { + RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); + factory.getRepository(null, DummyCollection.class, "dummy"); + } + + @After + public void cleanUp() throws Exception { + if (db != null && !db.isClosed()) { + db.close(); + } + TestUtil.deleteDb(fileName); + } + + private static class DummyCollection implements NitriteCollection { + + @Override + public WriteResult insert(Document document, Document... documents) { + return null; + } + + @Override + public WriteResult update(Filter filter, Document update, UpdateOptions updateOptions) { + return null; + } + + @Override + public WriteResult remove(Filter filter, boolean justOne) { + return null; + } + + @Override + public DocumentCursor find() { + return null; + } + + @Override + public DocumentCursor find(Filter filter) { + return null; + } + + @Override + public DocumentCursor find(Filter filter, FindOptions findOptions) { + return null; + } + + @Override + public Document getById(NitriteId nitriteId) { + return null; + } + + @Override + public String getName() { + return null; + } + + @Override + public void addProcessor(Processor processor) { + + } + + @Override + public void removeProcessor(Processor processor) { + + } + + @Override + public void createIndex(IndexOptions indexOptions, String... fields) { + + } + + @Override + public void rebuildIndex(String... fields) { + + } + + @Override + public Collection listIndices() { + return null; + } + + @Override + public boolean hasIndex(String... fields) { + return false; + } + + @Override + public boolean isIndexing(String... fields) { + return false; + } + + @Override + public void dropIndex(String... fields) { + + } + + @Override + public void dropAllIndices() { + + } + + @Override + public WriteResult insert(Document[] elements) { + return null; + } + + @Override + public WriteResult update(Document element, boolean insertIfAbsent) { + return null; + } + + @Override + public WriteResult remove(Document element) { + return null; + } + + @Override + public void clear() { + + } + + @Override + public void drop() { + + } + + @Override + public boolean isDropped() { + return false; + } + + @Override + public boolean isOpen() { + return false; + } + + @Override + public void close() { + + } + + @Override + public long size() { + return 0; + } + + @Override + public NitriteStore getStore() { + return null; + } + + @Override + public void subscribe(CollectionEventListener listener) { + + } + + @Override + public void unsubscribe(CollectionEventListener listener) { + + } + + @Override + public Attributes getAttributes() { + return null; + } + + @Override + public void setAttributes(Attributes attributes) { + + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryJoinTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryJoinTest.java new file mode 100644 index 000000000..4dacdbff8 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryJoinTest.java @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.Lookup; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Id; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.collection.FindOptions.skipBy; +import static org.dizitart.no2.filters.Filter.ALL; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class RepositoryJoinTest extends BaseObjectRepositoryTest { + private ObjectRepository personRepository; + private ObjectRepository
addressRepository; + + @Before + public void setUp() { + openDb(); + + personRepository = db.getRepository(Person.class); + addressRepository = db.getRepository(Address.class); + + for (int i = 0; i < 10; i++) { + Person person = new Person(); + person.setId(Integer.toString(i)); + person.setName("Person " + i); + personRepository.insert(person); + + Address address = new Address(); + address.setPersonId(Integer.toString(i)); + address.setStreet("Street address " + i); + addressRepository.insert(address); + + if (i == 5) { + Address address2 = new Address(); + address2.setPersonId(Integer.toString(i)); + address2.setStreet("Street address 2nd " + i); + addressRepository.insert(address2); + } + } + } + + @After + public void clear() throws Exception { + if (personRepository != null && !personRepository.isDropped()) { + personRepository.remove(ALL); + } + + if (addressRepository != null && !addressRepository.isDropped()) { + addressRepository.remove(ALL); + } + + super.clear(); + } + + @Test + public void testJoin() { + Lookup lookup = new Lookup(); + lookup.setLocalField("id"); + lookup.setForeignField("personId"); + lookup.setTargetField("addresses"); + + RecordStream result + = personRepository.find().join(addressRepository.find(), lookup, + PersonDetails.class); + assertEquals(result.size(), 10); + + for (PersonDetails personDetails : result) { + Address[] addresses = personDetails.addresses.toArray(new Address[0]); + if (personDetails.id.equals("5")) { + assertEquals(addresses.length, 2); + } else { + assertEquals(addresses.length, 1); + assertEquals(addresses[0].personId, personDetails.getId()); + } + } + + result = personRepository.find(skipBy(0).limit(5)).join(addressRepository.find(), lookup, + PersonDetails.class); + + assertEquals(result.size(), 5); + assertFalse(result.isEmpty()); + assertNotNull(result.toString()); + } + + @Test(expected = InvalidOperationException.class) + public void testRemove() { + Lookup lookup = new Lookup(); + lookup.setLocalField("id"); + lookup.setForeignField("personId"); + lookup.setTargetField("addresses"); + + RecordStream result + = personRepository.find().join(addressRepository.find(), lookup, + PersonDetails.class); + assertEquals(result.size(), 10); + + Iterator iterator = result.iterator(); + if (iterator.hasNext()) { + iterator.next(); + iterator.remove(); + } + } + + @Data + public static class Person implements Mappable { + @Id + private NitriteId nitriteId; + private String id; + private String name; + + @Override + public Document write(NitriteMapper mapper) { + return createDocument() + .put("nitriteId", nitriteId) + .put("id", id) + .put("name", name); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + nitriteId = document.get("nitriteId", NitriteId.class); + id = document.get("id", String.class); + name = document.get("name", String.class); + } + } + + @Data + public static class Address implements Mappable { + @Id + private NitriteId nitriteId; + private String personId; + private String street; + + @Override + public Document write(NitriteMapper mapper) { + return createDocument() + .put("nitriteId", nitriteId) + .put("personId", personId) + .put("street", street); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + nitriteId = document.get("nitriteId", NitriteId.class); + personId = document.get("personId", String.class); + street = document.get("street", String.class); + } + } + + @Data + public static class PersonDetails implements Mappable { + @Id + private NitriteId nitriteId; + private String id; + private String name; + private List
addresses; + + @Override + public Document write(NitriteMapper mapper) { + return createDocument() + .put("nitriteId", nitriteId) + .put("personId", id) + .put("street", name) + .put("addresses", addresses); + } + + @Override + @SuppressWarnings("unchecked") + public void read(NitriteMapper mapper, Document document) { + nitriteId = document.get("nitriteId", NitriteId.class); + id = document.get("id", String.class); + name = document.get("name", String.class); + Set documents = document.get("addresses", Set.class); + this.addresses = new ArrayList<>(); + for (Document doc : documents) { + Address address = new Address(); + address.read(mapper, doc); + addresses.add(address); + } + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryModificationTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryModificationTest.java new file mode 100644 index 000000000..d5bd0f5cb --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositoryModificationTest.java @@ -0,0 +1,657 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.integration.repository.data.*; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.exceptions.InvalidIdException; +import org.dizitart.no2.exceptions.UniqueConstraintException; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.Test; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Date; +import java.util.Locale; + +import static org.awaitility.Awaitility.await; +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + + +/** + * @author Anindya Chatterjee. + */ +public class RepositoryModificationTest extends BaseObjectRepositoryTest { + + @Test + public void testCreateIndex() { + assertTrue(companyRepository.hasIndex("companyName")); + assertFalse(companyRepository.hasIndex("dateCreated")); + + companyRepository.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "dateCreated"); + assertTrue(companyRepository.hasIndex("dateCreated")); + assertFalse(companyRepository.isIndexing("dateCreated")); + } + + @Test + public void testRebuildIndex() { + companyRepository.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "dateCreated"); + assertFalse(companyRepository.isIndexing("dateCreated")); + + companyRepository.rebuildIndex("dateCreated"); + // rebuild is sync + assertFalse(companyRepository.isIndexing("dateCreated")); + + await().until(() -> !companyRepository.isIndexing("dateCreated")); + } + + @Test + public void testListIndexes() { + Collection indices = companyRepository.listIndices(); + assertEquals(indices.size(), 2); + + companyRepository.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "dateCreated"); + indices = companyRepository.listIndices(); + assertEquals(indices.size(), 3); + } + + @Test + public void testDropIndex() { + testListIndexes(); + companyRepository.dropIndex("dateCreated"); + Collection indices = companyRepository.listIndices(); + assertEquals(indices.size(), 2); + } + + @Test + public void testDropAllIndex() { + testListIndexes(); + companyRepository.dropAllIndices(); + Collection indices = companyRepository.listIndices(); + assertEquals(indices.size(), 0); + } + + @Test + public void testCompanyRecord() { + Cursor cursor = companyRepository.find(); + assertEquals(cursor.size(), 10); + assertFalse(cursor.isEmpty()); + } + + @Test + public void testInsert() { + Company company = DataGenerator.generateCompanyRecord(); + Cursor cursor = companyRepository.find(); + assertEquals(cursor.size(), 10); + + companyRepository.insert(company); + cursor = companyRepository.find(); + assertEquals(cursor.size(), 11); + + Company company1 = DataGenerator.generateCompanyRecord(); + Company company2 = DataGenerator.generateCompanyRecord(); + companyRepository.insert(new Company[]{company1, company2}); + cursor = companyRepository.find(); + assertEquals(cursor.size(), 13); + } + + @Test + public void testUpdateWithFilter() { + employeeRepository.remove(Filter.ALL); + + Employee employee = new Employee(); + employee.setCompany(null); + employee.setAddress("abcd road"); + employee.setBlob(new byte[]{1, 2, 125}); + employee.setEmpId(12L); + employee.setJoinDate(new Date()); + Note empNote = new Note(); + empNote.setNoteId(23L); + empNote.setText("sample text note"); + employee.setEmployeeNote(empNote); + + employeeRepository.insert(employee); + Cursor result = employeeRepository.find(); + assertEquals(result.size(), 1); + for (Employee e : result) { + assertEquals(e.getAddress(), "abcd road"); + } + + Employee updated = new Employee(employee); + updated.setAddress("xyz road"); + WriteResult writeResult = employeeRepository.update(where("empId").eq(12L), updated); + assertEquals(writeResult.getAffectedCount(), 1); + result = employeeRepository.find(); + assertEquals(result.size(), 1); + for (Employee e : result) { + assertEquals(e.getAddress(), "xyz road"); + } + } + + @Test + public void testUpdateWithJustOnceFalse() throws ParseException { + Date joiningDate = new Date(); + prepareUpdateWithOptions(joiningDate); + + SimpleDateFormat simpleDateFormat + = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); + Date newJoiningDate = simpleDateFormat.parse("2012-07-01T16:02:48.440Z"); + + Document updated1 = createDocument(); + updated1.put("joinDate", newJoiningDate); + + WriteResult writeResult + = employeeRepository.update(where("empId").eq(12L), updated1, false); + assertEquals(writeResult.getAffectedCount(), 1); + + Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 1); + result = employeeRepository.find(where("joinDate").eq(newJoiningDate)); + assertEquals(result.size(), 1); + + employeeRepository.remove(Filter.ALL); + prepareUpdateWithOptions(joiningDate); + result = employeeRepository.find(); + assertEquals(result.size(), 2); + + Document update = createDocument(); + update.put("joinDate", newJoiningDate); + + writeResult = employeeRepository.update(where("joinDate").eq(joiningDate), update, false); + assertEquals(writeResult.getAffectedCount(), 2); + + result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 0); + + result = employeeRepository.find(where("joinDate").eq(newJoiningDate)); + assertEquals(result.size(), 2); + } + + @Test + public void testUpsertTrue() { + Date joiningDate = new Date(); + Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 0); + + Employee employee = new Employee(); + employee.setCompany(null); + employee.setAddress("some road"); + employee.setBlob(new byte[]{1, 2, 125}); + employee.setEmpId(12L); + employee.setJoinDate(joiningDate); + Note empNote1 = new Note(); + empNote1.setNoteId(23L); + empNote1.setText("sample text note"); + employee.setEmployeeNote(empNote1); + + WriteResult writeResult + = employeeRepository.update(where("empId").eq(12), employee, true); + assertEquals(writeResult.getAffectedCount(), 1); + + result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 1); + } + + @Test + public void testUpsertFalse() { + Date joiningDate = new Date(); + Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 0); + + Employee employee = new Employee(); + employee.setCompany(null); + employee.setAddress("some road"); + employee.setBlob(new byte[]{1, 2, 125}); + employee.setEmpId(12L); + employee.setJoinDate(joiningDate); + Note empNote1 = new Note(); + empNote1.setNoteId(23L); + empNote1.setText("sample text note"); + employee.setEmployeeNote(empNote1); + + WriteResult writeResult + = employeeRepository.update(where("empId").eq(12), employee, false); + assertEquals(writeResult.getAffectedCount(), 0); + + result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 0); + } + + @Test + public void testDeleteFilterAndWithOutOption() { + Date joiningDate = new Date(); + prepareUpdateWithOptions(joiningDate); + + Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 2); + + WriteResult writeResult = employeeRepository.remove(where("joinDate").eq(joiningDate)); + assertEquals(writeResult.getAffectedCount(), 2); + result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 0); + } + + @Test + public void testDeleteFilterAndWithOption() { + Date joiningDate = new Date(); + prepareUpdateWithOptions(joiningDate); + + Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 2); + + WriteResult writeResult = employeeRepository.remove(where("joinDate").eq(joiningDate), true); + assertEquals(writeResult.getAffectedCount(), 1); + result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 1); + } + + @Test + public void testEmployeeRecord() { + Iterable totalResult = employeeRepository.find(); + int occurrence = 0; + for (Employee employee : totalResult) { + if (employee.getEmployeeNote().getText().toLowerCase().contains("class aptent")) { + occurrence++; + } + } + + Cursor cursor = employeeRepository.find(where("employeeNote.text").text("Class aptent")); + assertEquals(cursor.size(), occurrence); + } + + @Test + public void testUpdateWithOptions() { + Employee employee = employeeRepository.find().firstOrNull(); + + Document update = createDocument(); + update.put("address", "new address"); + + WriteResult writeResult + = employeeRepository.update(where("empId").eq(employee.getEmpId()), update, false); + assertEquals(writeResult.getAffectedCount(), 1); + + Employee byId = employeeRepository.getById(employee.getEmpId()); + assertEquals(byId.getAddress(), "new address"); + assertEquals(byId.getEmpId(), employee.getEmpId()); + + update.put("address", "another address"); + employeeRepository.update(where("empId").eq(employee.getEmpId()), update); + + byId = employeeRepository.getById(employee.getEmpId()); + assertEquals(byId.getAddress(), "another address"); + assertEquals(byId.getEmpId(), employee.getEmpId()); + } + + @Test(expected = InvalidIdException.class) + public void testMultiUpdateWithObject() { + employeeRepository.remove(Filter.ALL); + + Date now = new Date(); + Employee employee1 = new Employee(); + employee1.setEmpId(1L); + employee1.setAddress("abcd"); + employee1.setJoinDate(now); + + Employee employee2 = new Employee(); + employee2.setEmpId(2L); + employee2.setAddress("xyz"); + employee2.setJoinDate(now); + employeeRepository.insert(employee1, employee2); + + Employee update = new Employee(); + update.setAddress("new address"); + + WriteResult writeResult + = employeeRepository.update(where("joinDate").eq(now), update, false); + assertEquals(writeResult.getAffectedCount(), 0); + } + + @Test + public void testUpdateNull() { + Employee employee = employeeRepository.find().firstOrNull(); + Employee newEmployee = new Employee(employee); + newEmployee.setJoinDate(null); + + Employee result = employeeRepository.find(where("empId").eq(employee.getEmpId())).firstOrNull(); + assertNotNull(result.getJoinDate()); + + WriteResult writeResult = employeeRepository.update(newEmployee, false); + assertEquals(writeResult.getAffectedCount(), 1); + + result = employeeRepository.find(where("empId").eq(employee.getEmpId())).firstOrNull(); + assertNull(result.getJoinDate()); + + // update with object filter and item and set id different + } + + @Test + public void testUpdateWithChangedId() { + Employee employee = employeeRepository.find().firstOrNull(); + Long oldId = employee.getEmpId(); + long count = employeeRepository.size(); + + Employee newEmployee = new Employee(employee); + newEmployee.setEmpId(50L); + + Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); + assertNotNull(result.getJoinDate()); + + WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); + assertEquals(writeResult.getAffectedCount(), 1); + + assertEquals(count, employeeRepository.size()); + Cursor cursor = employeeRepository.find(where("empId").eq(oldId)); + assertEquals(cursor.size(), 0); + } + + @Test(expected = InvalidIdException.class) + public void testUpdateWithNullId() { + Employee employee = employeeRepository.find().firstOrNull(); + Long oldId = employee.getEmpId(); + + Employee newEmployee = new Employee(employee); + newEmployee.setEmpId(null); + + Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); + assertNotNull(result.getJoinDate()); + + WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); + assertEquals(writeResult.getAffectedCount(), 1); + } + + @Test(expected = UniqueConstraintException.class) + public void testUpdateWithDuplicateId() { + Employee employee = employeeRepository.find().firstOrNull(); + Long oldId = employee.getEmpId(); + long count = employeeRepository.size(); + + Employee newEmployee = new Employee(employee); + newEmployee.setEmpId(5L); + + Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); + assertNotNull(result.getJoinDate()); + + WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); + assertEquals(writeResult.getAffectedCount(), 1); + + assertEquals(count, employeeRepository.size()); + Cursor cursor = employeeRepository.find(where("empId").eq(oldId)); + assertEquals(cursor.size(), 0); + } + + @Test + public void testUpdateWithObject() { + Employee employee = employeeRepository.find().firstOrNull(); + Employee newEmployee = new Employee(employee); + + Long id = employee.getEmpId(); + String address = employee.getAddress(); + newEmployee.setAddress("new address"); + + WriteResult writeResult = employeeRepository.update(newEmployee); + assertEquals(writeResult.getAffectedCount(), 1); + + Employee emp = employeeRepository.find(where("empId").eq(id)).firstOrNull(); + assertNotEquals(address, emp.getAddress()); + assertEquals(employee.getEmpId(), emp.getEmpId()); + assertEquals(employee.getJoinDate(), emp.getJoinDate()); + assertArrayEquals(employee.getBlob(), emp.getBlob()); + } + + @Test + public void testUpsertWithObject() { + Employee employee = new Employee(); + employee.setCompany(null); + employee.setAddress("some road"); + employee.setBlob(new byte[]{1, 2, 125}); + employee.setEmpId(12L); + employee.setJoinDate(new Date()); + Note empNote = new Note(); + empNote.setNoteId(23L); + empNote.setText("sample text note"); + employee.setEmployeeNote(empNote); + + WriteResult writeResult = employeeRepository.update(employee, false); + assertEquals(writeResult.getAffectedCount(), 0); + writeResult = employeeRepository.update(employee, true); + assertEquals(writeResult.getAffectedCount(), 1); + + Employee emp = employeeRepository.find(where("empId").eq(12L)).firstOrNull(); + assertEquals(emp, employee); + } + + @Test + public void testRemoveObject() { + Employee employee = new Employee(); + employee.setCompany(null); + employee.setAddress("some road"); + employee.setBlob(new byte[]{1, 2, 125}); + employee.setEmpId(12L); + employee.setJoinDate(new Date()); + Note empNote = new Note(); + empNote.setNoteId(23L); + empNote.setText("sample text note"); + employee.setEmployeeNote(empNote); + + long size = employeeRepository.size(); + + employeeRepository.insert(employee); + assertEquals(employeeRepository.size(), size + 1); + + employeeRepository.remove(employee); + assertEquals(employeeRepository.size(), size); + + Employee emp = employeeRepository.find(where("empId").eq(12L)).firstOrNull(); + assertNull(emp); + } + + private void prepareUpdateWithOptions(Date joiningDate) { + employeeRepository.remove(Filter.ALL); + + Employee employee1 = new Employee(); + employee1.setCompany(null); + employee1.setAddress("some road"); + employee1.setBlob(new byte[]{1, 2, 125}); + employee1.setEmpId(12L); + employee1.setJoinDate(joiningDate); + Note empNote1 = new Note(); + empNote1.setNoteId(23L); + empNote1.setText("sample text note"); + employee1.setEmployeeNote(empNote1); + + Employee employee2 = new Employee(); + employee2.setCompany(null); + employee2.setAddress("other road"); + employee2.setBlob(new byte[]{10, 12, 25}); + employee2.setEmpId(2L); + employee2.setJoinDate(joiningDate); + Note empNote2 = new Note(); + empNote2.setNoteId(2L); + empNote2.setText("some random note"); + employee2.setEmployeeNote(empNote2); + + employeeRepository.insert(employee1, employee2); + Cursor result = employeeRepository.find(); + assertEquals(result.size(), 2); + for (Employee e : result.project(Employee.class)) { + assertEquals(e.getJoinDate(), joiningDate); + } + } + + @Test + public void testUpdateWithDoc() { + Note note = new Note(); + note.setNoteId(10L); + note.setText("some note text"); + + Document document = createDocument("address", "some address") + .put("employeeNote", note); + + WriteResult result = employeeRepository.update(Filter.ALL, document); + assertEquals(result.getAffectedCount(), 10); + } + + @Test + public void testDeleteIteratorNPE() { + ObjectRepository notes = db.getRepository(Note.class); + Note one = new Note(); + one.setText("Jane"); + one.setNoteId(1L); + Note two = new Note(); + two.setText("Jill"); + two.setNoteId(2L); + + notes.insert(one, two); + + WriteResult writeResult = notes.remove(where("text").eq("Pete")); + for (NitriteId id : writeResult) { + assertNotNull(id); + } + } + + @Test + public void testDelete() { + ObjectRepository repo = db.getRepository(WithNitriteId.class); + WithNitriteId one = new WithNitriteId(); + one.setName("Jane"); + repo.insert(one); + + WithNitriteId note = repo.find().firstOrNull(); + repo.remove(note); + + assertNull(repo.getById(one.idField)); + } + + /* + * Upsert Use Cases + * + * 1. Object does not exists + * a. if upsert true, it will insert + * b. if upsert false, nothing happens + * 2. Object exists + * a. if upsert true, it will update, old id remains same + * b. if upsert false, it will update, old id remains same + * + * */ + + @Test + public void testUpdateObjectNotExistsUpsertTrue() { + ObjectRepository repo = db.getRepository(InternalClass.class); + InternalClass a = new InternalClass(); + a.setId(1); + a.setName("first"); + repo.insert(a); + + a = new InternalClass(); + a.setId(2); + a.setName("second"); + + // it will insert as new object + repo.update(a, true); + assertEquals(repo.size(), 2); + } + + @Test + public void testUpdateObjectNotExistsUpsertFalse() { + ObjectRepository repo = db.getRepository(InternalClass.class); + InternalClass a = new InternalClass(); + a.setId(1); + a.setName("first"); + repo.insert(a); + + a = new InternalClass(); + a.setId(2); + a.setName("second"); + + // no changes will happen to repository + repo.update(a, false); + assertEquals(repo.size(), 1); + assertEquals(repo.find().firstOrNull().getId(), 1); + assertEquals(repo.find().firstOrNull().getName(), "first"); + } + + @Test + public void testUpdateObjectExistsUpsertTrue() { + ObjectRepository repo = db.getRepository(InternalClass.class); + InternalClass a = new InternalClass(); + a.setId(1); + a.setName("first"); + repo.insert(a); + + a = new InternalClass(); + a.setId(1); + a.setName("second"); + + // update existing object, keep id same + repo.update(a, true); + assertEquals(repo.size(), 1); + assertEquals(repo.find().firstOrNull().getId(), 1); + assertEquals(repo.find().firstOrNull().getName(), "second"); + } + + @Test + public void testUpdateObjectExistsUpsertFalse() { + ObjectRepository repo = db.getRepository(InternalClass.class); + InternalClass a = new InternalClass(); + a.setId(1); + a.setName("first"); + repo.insert(a); + + a = new InternalClass(); + a.setId(1); + a.setName("second"); + + // update existing object, keep id same + repo.update(a, false); + assertEquals(repo.size(), 1); + assertEquals(repo.find().firstOrNull().getId(), 1); + assertEquals(repo.find().firstOrNull().getName(), "second"); + } + + @Test + public void testNestedUpdate() { + Employee employee = employeeRepository.getById(1L); + assertNotNull(employee); + + Note note = employee.getEmployeeNote(); + String text = note.getText(); + assertNotNull(text); + + Document update = createDocument("employeeNote.text", "some updated text"); + WriteResult writeResult = employeeRepository.update(where("empId").eq(1L), update, true); + assertEquals(1, writeResult.getAffectedCount()); + + employee = employeeRepository.getById(1L); + assertNotNull(employee); + + note = employee.getEmployeeNote(); + assertNotNull(note); + assertNotEquals(text, note.getText()); + assertEquals("some updated text", note.getText()); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositorySearchTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositorySearchTest.java new file mode 100644 index 000000000..68015c9f3 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/RepositorySearchTest.java @@ -0,0 +1,609 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import lombok.Getter; +import org.dizitart.no2.integration.repository.data.*; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.exceptions.InvalidIdException; +import org.dizitart.no2.exceptions.NotIdentifiableException; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.Test; + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.List; + +import static org.dizitart.no2.collection.FindOptions.orderBy; +import static org.dizitart.no2.collection.FindOptions.skipBy; +import static org.dizitart.no2.filters.Filter.*; +import static org.dizitart.no2.filters.FluentFilter.$; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class RepositorySearchTest extends BaseObjectRepositoryTest { + @Test + public void testFindWithOptions() { + Cursor cursor = employeeRepository.find(skipBy(0).limit(1)); + assertEquals(cursor.size(), 1); + assertNotNull(cursor.firstOrNull()); + } + + @Test + public void testEmployeeProjection() { + List employeeList = employeeRepository.find().toList(); + List subEmployeeList + = employeeRepository.find().project(SubEmployee.class).toList(); + + assertNotNull(employeeList); + assertNotNull(subEmployeeList); + + assertTrue(employeeList.size() > 0); + assertTrue(subEmployeeList.size() > 0); + + assertEquals(employeeList.size(), subEmployeeList.size()); + + for (int i = 0; i < subEmployeeList.size(); i++) { + Employee employee = employeeList.get(i); + SubEmployee subEmployee = subEmployeeList.get(i); + + assertEquals(employee.getEmpId(), subEmployee.getEmpId()); + assertEquals(employee.getJoinDate(), subEmployee.getJoinDate()); + assertEquals(employee.getAddress(), subEmployee.getAddress()); + } + + Cursor cursor = employeeRepository.find(); + assertNotNull(cursor.firstOrNull()); + assertNotNull(cursor.toString()); + assertEquals(cursor.toList().size(), employeeList.size()); + assertNotNull(cursor.firstOrNull()); + assertEquals(cursor.toList().size(), employeeList.size()); + } + + @Test + public void testEmptyResultProjection() { + employeeRepository.remove(ALL); + assertNull(employeeRepository.find().firstOrNull()); + + assertNull(employeeRepository.find(where("empId").eq(-1)) + .firstOrNull()); + } + + @Test + public void testGetById() { + ObjectRepository empRepo = db.getRepository(Employee.class); + Employee e1 = DataGenerator.generateEmployee(); + Employee e2 = DataGenerator.generateEmployee(); + Employee e3 = DataGenerator.generateEmployee(); + Employee e4 = DataGenerator.generateEmployee(); + + e1.setEmpId(1000000L); + e2.setEmpId(2000000L); + e3.setEmpId(3000000L); + e4.setEmpId(4000000L); + + empRepo.insert(e1, e2, e3, e4); + + Employee byId = empRepo.getById(2000000L); + assertEquals(byId, e2); + } + + @Test(expected = NotIdentifiableException.class) + public void testGetByIdNoId() { + ObjectRepository repository = db.getRepository(Note.class); + Note n1 = DataGenerator.randomNote(); + Note n2 = DataGenerator.randomNote(); + Note n3 = DataGenerator.randomNote(); + + n1.setNoteId(1000000L); + n2.setNoteId(2000000L); + n3.setNoteId(3000000L); + + repository.insert(n1, n2, n3); + + repository.getById(2000000L); + } + + @Test(expected = InvalidIdException.class) + public void testGetByIdNullId() { + ObjectRepository empRepo = db.getRepository(Employee.class); + Employee e1 = DataGenerator.generateEmployee(); + Employee e2 = DataGenerator.generateEmployee(); + Employee e3 = DataGenerator.generateEmployee(); + Employee e4 = DataGenerator.generateEmployee(); + + e1.setEmpId(1000000L); + e2.setEmpId(2000000L); + e3.setEmpId(3000000L); + e4.setEmpId(4000000L); + + empRepo.insert(e1, e2, e3, e4); + + empRepo.getById(null); + } + + @Test(expected = InvalidIdException.class) + public void testGetByIdWrongType() { + ObjectRepository empRepo = db.getRepository(Employee.class); + Employee e1 = DataGenerator.generateEmployee(); + Employee e2 = DataGenerator.generateEmployee(); + Employee e3 = DataGenerator.generateEmployee(); + Employee e4 = DataGenerator.generateEmployee(); + + e1.setEmpId(1000000L); + e2.setEmpId(2000000L); + e3.setEmpId(3000000L); + e4.setEmpId(4000000L); + + empRepo.insert(e1, e2, e3, e4); + + Employee byId = empRepo.getById("employee"); + assertNull(byId); + } + + @Test + public void testEqualFilterById() { + Employee employee = employeeRepository.find().firstOrNull(); + long empId = employee.getEmpId(); + Employee emp = employeeRepository.find(where("empId").eq(empId)) + .project(Employee.class).firstOrNull(); + assertEquals(employee, emp); + } + + @Test + public void testEqualFilter() { + Employee employee = employeeRepository.find() + .firstOrNull(); + + Employee emp = employeeRepository.find(where("joinDate").eq(employee.getJoinDate())) + .project(Employee.class) + .firstOrNull(); + assertEquals(employee, emp); + } + + @Test + public void testStringEqualFilter() { + ObjectRepository repository = db.getRepository(ProductScore.class); + + ProductScore object = new ProductScore(); + object.setProduct("test"); + object.setScore(1); + repository.insert(object); + + object = new ProductScore(); + object.setProduct("test"); + object.setScore(2); + repository.insert(object); + + object = new ProductScore(); + object.setProduct("another-test"); + object.setScore(3); + repository.insert(object); + + assertEquals(repository.find(where("product").eq("test")).size(), 2); + } + + @Test + public void testAndFilter() { + Employee emp = employeeRepository.find().firstOrNull(); + + long id = emp.getEmpId(); + String address = emp.getAddress(); + Date joinDate = emp.getJoinDate(); + + Cursor cursor = employeeRepository.find( + and( + where("empId").eq(id), + where("address").regex(address), + where("joinDate").eq(joinDate) + ) + ); + Employee employee = cursor.firstOrNull(); + + assertEquals(emp, employee); + } + + @Test + public void testOrFilter() { + Employee emp = employeeRepository.find().firstOrNull(); + long id = emp.getEmpId(); + + Employee employee = employeeRepository.find( + or( + where("empId").eq(id), + where("address").text("n/a"), + where("joinDate").eq(null) + )).firstOrNull(); + + assertEquals(emp, employee); + } + + @Test + public void testNotFilter() { + Employee emp = employeeRepository.find().firstOrNull(); + long id = emp.getEmpId(); + + Employee employee = employeeRepository.find( + where("empId").eq(id).not()).firstOrNull(); + assertNotEquals(emp, employee); + } + + @Test + public void testGreaterFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Ascending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").gt(id)) + .toList(); + + assertFalse(employeeList.contains(emp)); + assertEquals(employeeList.size(), 9); + } + + @Test + public void testGreaterEqualFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Ascending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").gte(id)) + .toList(); + + assertTrue(employeeList.contains(emp)); + assertEquals(employeeList.size(), 10); + } + + @Test + public void testLesserThanFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Descending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").lt(id)) + .toList(); + + assertFalse(employeeList.contains(emp)); + assertEquals(employeeList.size(), 9); + } + + @Test + public void testLesserEqualFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Descending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").lte(id)) + .toList(); + + assertTrue(employeeList.contains(emp)); + assertEquals(employeeList.size(), 10); + } + + @Test + public void testTextFilter() { + Employee emp = employeeRepository.find().firstOrNull(); + String text = emp.getEmployeeNote().getText(); + + List employeeList = employeeRepository.find(where("employeeNote.text").text(text)) + .toList(); + + assertTrue(employeeList.contains(emp)); + } + + @Test + public void testRegexFilter() { + Cursor employees = employeeRepository.find(); + int count = employees.toList().size(); + + List employeeList = employeeRepository.find(where("emailAddress") + .regex("^[a-zA-Z0-9+_.-]+@[a-zA-Z0-9.-]+$")) + .toList(); + + assertEquals(employeeList.size(), count); + } + + @Test + public void testInFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Descending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").in(id, id - 1, id - 2)) + .toList(); + + assertTrue(employeeList.contains(emp)); + assertEquals(employeeList.size(), 3); + + employeeList = employeeRepository.find(where("empId").in(id - 1, id - 2)).toList(); + assertEquals(employeeList.size(), 2); + } + + @Test + public void testNotInFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Descending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").notIn(id, id - 1, id - 2)) + .toList(); + + assertFalse(employeeList.contains(emp)); + assertEquals(employeeList.size(), 7); + + employeeList = employeeRepository.find(where("empId").notIn(id - 1, id - 2)).toList(); + assertEquals(employeeList.size(), 8); + } + + @Test + public void testElemMatchFilter() { + final ProductScore score1 = new ProductScore("abc", 10); + final ProductScore score2 = new ProductScore("abc", 8); + final ProductScore score3 = new ProductScore("abc", 7); + final ProductScore score4 = new ProductScore("xyz", 5); + final ProductScore score5 = new ProductScore("xyz", 7); + final ProductScore score6 = new ProductScore("xyz", 8); + + ObjectRepository repository = db.getRepository(ElemMatch.class); + ElemMatch e1 = new ElemMatch() {{ + setId(1); + setStrArray(new String[]{"a", "b"}); + setProductScores(new ProductScore[]{score1, score4}); + }}; + ElemMatch e2 = new ElemMatch() {{ + setId(2); + setStrArray(new String[]{"d", "e"}); + setProductScores(new ProductScore[]{score2, score5}); + }}; + ElemMatch e3 = new ElemMatch() {{ + setId(3); + setStrArray(new String[]{"a", "f"}); + setProductScores(new ProductScore[]{score3, score6}); + }}; + + repository.insert(e1, e2, e3); + + List elements = repository.find( + where("productScores").elemMatch( + where("product").eq("xyz") + .and(where("score").gte(8)))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("score").lte(8).not())).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("product").eq("xyz") + .or(where("score").gte(8)))).toList(); + assertEquals(elements.size(), 3); + + elements = repository.find( + where("productScores").elemMatch( + where("product").eq("xyz"))).toList(); + assertEquals(elements.size(), 3); + + elements = repository.find( + where("productScores").elemMatch( + where("score").gte(10))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("score").gt(8))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("score").lt(7))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("score").lte(7))).toList(); + assertEquals(elements.size(), 3); + + elements = repository.find( + where("productScores").elemMatch( + where("score").in(7, 8))).toList(); + assertEquals(elements.size(), 2); + + elements = repository.find( + where("productScores").elemMatch( + where("score").notIn(7, 8))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("product").regex("xyz"))).toList(); + assertEquals(elements.size(), 3); + + elements = repository.find(where("strArray").elemMatch($.eq("a"))).toList(); + assertEquals(elements.size(), 2); + + elements = repository.find( + where("strArray").elemMatch( + $.eq("a") + .or($.eq("f") + .or($.eq("b"))).not())).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find(where("strArray").elemMatch($.gt("e"))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find(where("strArray").elemMatch($.gte("e"))).toList(); + assertEquals(elements.size(), 2); + + elements = repository.find(where("strArray").elemMatch($.lte("b"))).toList(); + assertEquals(elements.size(), 2); + + elements = repository.find(where("strArray").elemMatch($.lt("a"))).toList(); + assertEquals(elements.size(), 0); + + elements = repository.find(where("strArray").elemMatch($.in("a", "f"))).toList(); + assertEquals(elements.size(), 2); + + elements = repository.find(where("strArray").elemMatch($.regex("a"))).toList(); + assertEquals(elements.size(), 2); + } + + @Test + public void testFilterAll() { + ObjectRepository repository = db.getRepository(ElemMatch.class); + Cursor cursor = repository.find(ALL); + assertNotNull(cursor); + assertEquals(cursor.size(), 0); + + repository.insert(new ElemMatch()); + cursor = repository.find(ALL); + assertNotNull(cursor); + assertEquals(cursor.size(), 1); + } + + @Test(expected = FilterException.class) + public void testEqualsOnTextIndex() { + PersonEntity p1 = new PersonEntity("jhonny"); + PersonEntity p2 = new PersonEntity("jhonny"); + PersonEntity p3 = new PersonEntity("jhonny"); + + ObjectRepository repository = db.getRepository(PersonEntity.class); + repository.insert(p1); + repository.insert(p2); + repository.insert(p3); + + List sameNamePeople = repository.find(where("name").eq("jhonny")).toList(); + assertEquals(sameNamePeople.size(), 3); + + sameNamePeople = repository.find(where("name").eq("JHONNY")).toList(); + assertEquals(sameNamePeople.size(), 0); + + sameNamePeople = repository.find(where("name").text("jhonny")).toList(); + assertEquals(sameNamePeople.size(), 3); + + sameNamePeople = repository.find(where("name").text("JHONNY")).toList(); + assertEquals(sameNamePeople.size(), 3); + + sameNamePeople = repository.find(where("name").eq("jhon*")).toList(); + assertEquals(sameNamePeople.size(), 0); + + sameNamePeople = repository.find(where("name").text("jhon*")).toList(); + assertEquals(sameNamePeople.size(), 3); + } + + @Test + public void testIssue62() { + PersonEntity p1 = new PersonEntity("abcd"); + p1.setStatus("Married"); + + PersonEntity p2 = new PersonEntity("efgh"); + p2.setStatus("Married"); + + PersonEntity p3 = new PersonEntity("ijkl"); + p3.setStatus("Un-Married"); + + ObjectRepository repository = db.getRepository(PersonEntity.class); + repository.insert(p1); + repository.insert(p2); + repository.insert(p3); + + Filter married = where("status").eq("Married"); + + assertEquals(repository.find(married).size(), 2); + assertEquals(repository.find(married, orderBy("status", SortOrder.Descending)).size(), 2); + + assertEquals(repository.find(orderBy("status", SortOrder.Descending)).firstOrNull().getStatus(), "Un-Married"); + + assertEquals(repository.find(orderBy("status", SortOrder.Ascending)).size(), 3); + assertEquals(repository.find(orderBy("status", SortOrder.Ascending)).firstOrNull().getStatus(), "Married"); + } + + @Test + public void testRepeatableIndexAnnotation() { + ObjectRepository repo = db.getRepository(RepeatableIndexTest.class); + RepeatableIndexTest first = new RepeatableIndexTest(); + first.setAge(12); + first.setFirstName("fName"); + first.setLastName("lName"); + repo.insert(first); + + assertTrue(repo.hasIndex("firstName")); + assertTrue(repo.hasIndex("age")); + assertTrue(repo.hasIndex("lastName")); + + assertEquals(repo.find(where("age").eq(12)).firstOrNull(), first); + } + + @Test + public void testIdSet() { + Cursor employees = employeeRepository.find(orderBy("empId", SortOrder.Ascending)); + assertEquals(employees.size(), 10); + } + + @Test + public void testBetweenFilter() { + @Getter + class TestData implements Mappable { + private Date age; + + public TestData(Date age) { + this.age = age; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("age", age); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + age = document.get("age", Date.class); + } + } + + TestData data1 = new TestData(new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime()); + TestData data2 = new TestData(new GregorianCalendar(2021, Calendar.FEBRUARY, 12).getTime()); + TestData data3 = new TestData(new GregorianCalendar(2022, Calendar.MARCH, 13).getTime()); + TestData data4 = new TestData(new GregorianCalendar(2023, Calendar.APRIL, 14).getTime()); + TestData data5 = new TestData(new GregorianCalendar(2024, Calendar.MAY, 15).getTime()); + TestData data6 = new TestData(new GregorianCalendar(2025, Calendar.JUNE, 16).getTime()); + + ObjectRepository repository = db.getRepository(TestData.class); + repository.insert(data1, data2, data3, data4, data5, data6); + + Cursor cursor = repository.find(where("age").between( + new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), + new GregorianCalendar(2025, Calendar.JUNE, 16).getTime())); + assertEquals(cursor.size(), 6); + + cursor = repository.find(where("age").between( + new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), + new GregorianCalendar(2025, Calendar.JUNE, 16).getTime(), false)); + assertEquals(cursor.size(), 4); + + cursor = repository.find(where("age").between( + new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), + new GregorianCalendar(2025, Calendar.JUNE, 16).getTime(), false, true)); + assertEquals(cursor.size(), 5); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/UnAnnotatedObjectTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/UnAnnotatedObjectTest.java new file mode 100644 index 000000000..cf793fb10 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/UnAnnotatedObjectTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + + +import org.dizitart.no2.integration.repository.data.ClassA; +import org.dizitart.no2.integration.repository.data.ClassC; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.repository.Cursor; +import org.junit.Test; + +import static org.dizitart.no2.collection.FindOptions.orderBy; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +/** + * @author Anindya Chatterjee. + */ +public class UnAnnotatedObjectTest extends BaseObjectRepositoryTest { + + @Test + public void testFind() { + Cursor cursor = aObjectRepository.find(); + assertEquals(cursor.size(), 10); + assertFalse(cursor.isEmpty()); + + aObjectRepository.createIndex("b.number"); + + cursor = aObjectRepository.find(where("b.number").eq(160).not(), + orderBy("b.number", SortOrder.Ascending).skip(0).limit(10)); + + System.out.println("Available - " + !cursor.isEmpty()); + System.out.println("Total Size - " + cursor.size()); + + Iterable findRecord = cursor.project(ClassA.class); + for (ClassA classA : findRecord) { + System.out.println(classA); + } + + cursor = aObjectRepository.find(where("b.number").eq(160).not(), + orderBy("b.number", SortOrder.Descending).skip(2).limit(7)); + + System.out.println("Available - " + !cursor.isEmpty()); + System.out.println("Total Size - " + cursor.size()); + + findRecord = cursor.project(ClassA.class); + for (ClassA classA : findRecord) { + System.out.println(classA); + } + + cursor = cObjectRepository.find(where("id").gt(900), + orderBy("id", SortOrder.Descending).skip(2).limit(7)); + System.out.println("Available - " + !cursor.isEmpty()); + System.out.println("Total Size - " + cursor.size()); + + Iterable findRecordC = cursor.project(ClassC.class); + for (ClassC classC : findRecordC) { + System.out.println(classC); + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/UniversalTextTokenizerTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/UniversalTextTokenizerTest.java new file mode 100644 index 000000000..8b2237f0b --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/UniversalTextTokenizerTest.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteBuilder; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.index.NitriteTextIndexer; +import org.dizitart.no2.index.fulltext.Languages; +import org.dizitart.no2.index.fulltext.UniversalTextTokenizer; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Index; +import org.dizitart.no2.repository.annotations.Indices; +import org.dizitart.no2.rocksdb.RocksDBModule; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static org.dizitart.no2.common.module.NitriteModule.module; +import static org.dizitart.no2.filters.Filter.ALL; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +/** + * @author Anindya Chatterjee + */ +public class UniversalTextTokenizerTest extends BaseObjectRepositoryTest { + private final String fileName = getRandomTempDbFile(); + private ObjectRepository textRepository; + + @Before + @Override + public void setUp() { + openDb(); + textRepository = db.getRepository(TextData.class); + + for (int i = 0; i < 10; i++) { + TextData data = new TextData(); + data.id = i; + if (i % 2 == 0) { + data.text = "তারা বলল, “এস আমরা আমাদের জন্যে এক বড় শহর বানাই| আর এমন একটি উঁচু স্তম্ভ বানাই " + + "যা আকাশ স্পর্শ করবে| তাহলে আমরা বিখ্যাত হব এবং এটা আমাদের এক সঙ্গে ধরে রাখবে| সারা পৃথিবীতে " + + "আমরা ছড়িয়ে থাকব না|”"; + } else if (i % 3 == 0) { + data.text = "部汁楽示時葉没式将場参右属。覧観将者雄日語山銀玉襲政著約域費。新意虫跡更味株付安署審完顔団。" + + "困更表転定一史賀面政巣迎文学豊税乗。白間接特時京転閉務講封新内。側流効表害場測投活聞秀職探画労。" + + "福川順式極木注美込行警検直性禁遅。土一詳非物質紙姿漢人内池銀周街躍澹二。平討聞述並時全経詳業映回作朝送恵時。"; + } else if (i % 5 == 0) { + data.text = " أقبل لسفن العالم، في أما, بـ بال أملاً الثالث،. الذود بالرّد الثالث، مع" + + " قام, كردة الضغوط الإمداد أن وصل. ٠٨٠٤ عُقر انتباه يكن قد, أن زهاء وفنلندا بال. لان ما يقوم المعاهدات," + + " بـ بخطوط استعملت عدد. صفحة لفشل ولاتّساع لم قام, في مكثّفة الكونجرس جعل, الثالث، واقتصار دون ان.\n"; + } else { + data.text = "Lorem ipsum dolor sit amet, nobis audire perpetua eu sea. Te semper causae " + + "efficiantur per. Qui affert dolorum at. Mel tale constituto interesset in."; + } + textRepository.insert(data); + } + } + + @After + @Override + public void clear() throws Exception { + if (textRepository != null && !textRepository.isDropped()) { + textRepository.remove(ALL); + } + + if (db != null) { + db.commit(); + db.close(); + } + + deleteDb(fileName); + } + + @Override + protected void openDb() { + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(fileName) + .build(); + + NitriteBuilder nitriteBuilder = Nitrite.builder() + .fieldSeparator(".") + .loadModule(storeModule); + + UniversalTextTokenizer tokenizer; + if (isProtected) { + tokenizer = new UniversalTextTokenizer(Languages.Bengali, Languages.Chinese, Languages.English); + } else { + tokenizer = new UniversalTextTokenizer(Languages.ALL); + } + nitriteBuilder.loadModule(module(new NitriteTextIndexer(tokenizer))); + + if (isProtected) { + db = nitriteBuilder.openOrCreate("test-user", "test-password"); + } else { + db = nitriteBuilder.openOrCreate(); + } + } + + @Test + public void testUniversalFullTextIndexing() { + Cursor cursor = textRepository.find(where("text").text("Lorem")); + assertEquals(cursor.size(), 2); + for (TextData data : cursor) { + System.out.println("Id for English text -> " + data.id); + if (data.id % 2 == 0 || data.id % 3 == 0 || data.id % 5 == 0) { + fail(); + } + } + + cursor = textRepository.find(where("text").text("শহর")); + assertEquals(cursor.size(), 5); + for (TextData data : cursor) { + System.out.println("Id for Bengali text -> " + data.id); + if (data.id % 2 != 0) { + fail(); + } + } + + cursor = textRepository.find(where("text").text("転閉")); + assertEquals(cursor.size(), 0); + cursor = textRepository.find(where("text").text("*転閉*")); + assertEquals(cursor.size(), 2); + for (TextData data : cursor) { + System.out.println("Id for Chinese text -> " + data.id); + if (data.id % 3 != 0) { + fail(); + } + } + + cursor = textRepository.find(where("text").text("أقبل")); + if (isProtected) { + assertEquals(cursor.size(), 1); + for (TextData data : cursor) { + System.out.println("Id for Arabic text -> " + data.id); + if (data.id % 5 != 0) { + fail(); + } + } + } else { + // أقبل eliminated as stop word + assertEquals(cursor.size(), 0); + } + } + + @Indices( + @Index(value = "text", type = IndexType.FULL_TEXT) + ) + public static class TextData implements Mappable { + public int id; + public String text; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("id", id) + .put("text", text); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Integer.class); + text = document.get("text", String.class); + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Book.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Book.java new file mode 100644 index 000000000..5a147769c --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Book.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.repository.annotations.Entity; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +import java.util.List; + +import static org.dizitart.no2.collection.Document.createDocument; + +/** + * @author Anindya Chatterjee + */ +@Data +@Entity(value = "books", indices = { + @Index(value = "tags", type = IndexType.NON_UNIQUE), + @Index(value = "description", type = IndexType.FULL_TEXT), + @Index(value = { "price", "publisher" }) +}) +public class Book implements Mappable { + @Id(fieldName = "book_id") + private BookId bookId; + + private String publisher; + + private Double price; + + private List tags; + + private String description; + + @Override + public Document write(NitriteMapper mapper) { + return createDocument("book_id", mapper.convert(bookId, Document.class)) + .put("publisher", publisher) + .put("price", price) + .put("tags", tags) + .put("description", description); + } + + @Override + @SuppressWarnings("unchecked") + public void read(NitriteMapper mapper, Document document) { + bookId = mapper.convert(document.get("book_id"), BookId.class); + publisher = document.get("publisher", String.class); + price = document.get("price", Double.class); + tags = (List) document.get("tags", List.class); + description = document.get("description", String.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/BookId.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/BookId.java new file mode 100644 index 000000000..239b493d3 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/BookId.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Embedded; + +import static org.dizitart.no2.collection.Document.createDocument; + +/** + * @author Anindya Chatterjee + */ +@Data +public class BookId implements Mappable { + @Embedded(order = 0) + private String isbn; + + @Embedded(order = 1, fieldName = "book_name") + private String name; + + private String author; + + @Override + public Document write(NitriteMapper mapper) { + return createDocument("isbn", isbn) + .put("book_name", name) + .put("author", author); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + isbn = document.get("isbn", String.class); + name = document.get("book_name", String.class); + author = document.get("author", String.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ChildClass.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ChildClass.java new file mode 100644 index 000000000..d3c2ba644 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ChildClass.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.InheritIndices; + +/** + * @author Anindya Chatterjee + */ +@Getter +@Setter +@InheritIndices +public class ChildClass extends ParentClass { + private String name; + + @Override + public Document write(NitriteMapper mapper) { + return super.write(mapper).put("name", name); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + super.read(mapper, document); + name = document.get("name", String.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ClassA.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ClassA.java new file mode 100644 index 000000000..a8161c4e2 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ClassA.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +import java.util.UUID; + +@EqualsAndHashCode +@ToString +public class ClassA implements Mappable { + @Getter + @Setter + private ClassB b; + @Getter + @Setter + private UUID uid; + @Getter + @Setter + private String string; + @Getter + @Setter + private byte[] blob; + + public static ClassA create(int seed) { + ClassB classB = ClassB.create(seed); + ClassA classA = new ClassA(); + classA.b = classB; + classA.uid = new UUID(seed, seed + 50); + classA.string = Integer.toHexString(seed); + classA.blob = new byte[]{(byte) seed}; + return classA; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("b", b != null ? b.write(mapper) : null) + .put("uid", uid) + .put("string", string) + .put("blob", blob); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + if (document.get("b") != null) { + b = new ClassB(); + b.read(mapper, document.get("b", Document.class)); + } + uid = document.get("uid", UUID.class); + string = document.get("string", String.class); + blob = document.get("blob", byte[].class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ClassB.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ClassB.java new file mode 100644 index 000000000..a546b91e2 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ClassB.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +@EqualsAndHashCode +@ToString +class ClassB implements Comparable, Mappable { + @Getter + @Setter + private int number; + @Getter + @Setter + private String text; + + static ClassB create(int seed) { + ClassB classB = new ClassB(); + classB.setNumber(seed + 100); + classB.setText(Integer.toBinaryString(seed)); + return classB; + } + + @Override + public int compareTo(ClassB o) { + return Integer.compare(number, o.number); + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("number", number) + .put("text", text); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + number = document.get("number", Integer.class); + text = document.get("text", String.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ClassC.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ClassC.java new file mode 100644 index 000000000..860fe1e93 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ClassC.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +@EqualsAndHashCode +@ToString +public class ClassC implements Mappable { + @Getter + @Setter + private long id; + @Getter + @Setter + private double digit; + @Getter + @Setter + private ClassA parent; + + public static ClassC create(int seed) { + ClassC classC = new ClassC(); + classC.id = seed * 5000L; + classC.digit = seed * 69.65; + classC.parent = ClassA.create(seed); + return classC; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("id", id) + .put("digit", digit) + .put("parent", parent != null ? parent.write(mapper) : null); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Long.class); + digit = document.get("digit", Double.class); + if (document.get("parent") != null) { + parent = new ClassA(); + parent.read(mapper, document.get("parent", Document.class)); + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Company.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Company.java new file mode 100644 index 000000000..944e17358 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Company.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; +import org.dizitart.no2.repository.annotations.Indices; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @author Anindya Chatterjee. + */ +@EqualsAndHashCode +@Indices({ + @Index(value = "companyName") +}) +public class Company implements Serializable, Mappable { + @Id(fieldName = "company_id") + @Getter + @Setter + private Long companyId; + + @Getter + @Setter + private String companyName; + + @Getter + @Setter + private Date dateCreated; + + @Getter + @Setter + private List departments; + + @Getter + @Setter + private Map> employeeRecord; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("company_id", companyId) + .put("companyName", companyName) + .put("dateCreated", dateCreated) + .put("departments", departments) + .put("employeeRecord", employeeRecord); + } + + @Override + @SuppressWarnings("unchecked") + public void read(NitriteMapper mapper, Document document) { + companyId = document.get("company_id", Long.class); + companyName = document.get("companyName", String.class); + dateCreated = document.get("dateCreated", Date.class); + departments = document.get("departments", List.class); + employeeRecord = document.get("employeeRecord", Map.class); + } + + @Override + public String toString() { + return "Company{" + + "companyId=" + companyId + + ", companyName='" + companyName + '\'' + + ", dateCreated=" + dateCreated + + ", departments=" + departments + + '}'; + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/DataGenerator.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/DataGenerator.java new file mode 100644 index 000000000..26e0dcf4a --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/DataGenerator.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import com.github.javafaker.Faker; +import lombok.val; + +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author Anindya Chatterjee. + */ +public class DataGenerator { + private static final Random random = new Random(System.currentTimeMillis()); + private static final AtomicInteger counter = new AtomicInteger(random.nextInt()); + private static final Faker faker = new Faker(random); + + private DataGenerator() {} + + public static Company generateCompanyRecord() { + Company company = new Company(); + company.setCompanyId(System.nanoTime() + counter.incrementAndGet()); + company.setCompanyName(faker.company().name()); + company.setDateCreated(faker.date().past(10, TimeUnit.DAYS)); + List departments = departments(); + company.setDepartments(departments); + + Map> employeeRecord = new HashMap<>(); + for (String department : departments) { + employeeRecord.put(department, + generateEmployeeRecords(company, random.nextInt(20))); + } + company.setEmployeeRecord(employeeRecord); + return company; + } + + private static List generateEmployeeRecords(Company company, int count) { + List employeeList = new ArrayList<>(); + for (int i = 0; i < count; i++) { + Employee employee = generateEmployee(); + employee.setCompany(company); + employeeList.add(employee); + } + return employeeList; + } + + public static Employee generateEmployee() { + Employee employee = new Employee(); + employee.setEmpId(System.nanoTime() + counter.incrementAndGet()); + employee.setJoinDate(faker.date().birthday()); + employee.setAddress(faker.address().fullAddress()); + + employee.setBlob(faker.lorem().paragraph().getBytes(StandardCharsets.UTF_8)); + employee.setEmployeeNote(randomNote()); + employee.setEmailAddress(faker.internet().emailAddress()); + + return employee; + } + + public static Note randomNote() { + Note note = new Note(); + note.setNoteId(System.nanoTime() + counter.incrementAndGet()); + note.setText(faker.lorem().paragraph()); + return note; + } + + public static Book randomBook() { + BookId bookId = new BookId(); + val bookFaker = faker.book(); + bookId.setIsbn(faker.idNumber().ssnValid()); + bookId.setAuthor(bookFaker.author()); + bookId.setName(bookFaker.title()); + + Book book = new Book(); + book.setBookId(bookId); + book.setDescription(faker.backToTheFuture().quote()); + book.setPrice(faker.number().randomDouble(2, 100, 500)); + book.setPublisher(bookFaker.publisher()); + List tags = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + tags.add(bookFaker.genre()); + } + book.setTags(tags); + return book; + } + + private static List departments() { + return new ArrayList() {{ + add("dev"); + add("hr"); + add("qa"); + add("dev-ops"); + add("sales"); + add("marketing"); + add("design"); + add("support"); + }}; + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ElemMatch.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ElemMatch.java new file mode 100644 index 000000000..cb5304e29 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ElemMatch.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Anindya Chatterjee + */ +@Data +public class ElemMatch implements Mappable { + private long id; + private String[] strArray; + private ProductScore[] productScores; + + @Override + public Document write(NitriteMapper mapper) { + List list = new ArrayList<>(); + if (productScores != null) { + for (ProductScore productScore : productScores) { + Document document = productScore.write(mapper); + list.add(document); + } + } + + return Document.createDocument("id", id) + .put("strArray", strArray) + .put("productScores", list); + } + + @Override + @SuppressWarnings("unchecked") + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Long.class); + strArray = document.get("strArray", String[].class); + List list = document.get("productScores", List.class); + if (list != null) { + productScores = new ProductScore[list.size()]; + for (int i = 0; i < list.size(); i++) { + productScores[i] = new ProductScore(); + productScores[i].read(mapper, list.get(i)); + } + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Employee.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Employee.java new file mode 100644 index 000000000..7204f5654 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Employee.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author Anindya Chatterjee. + */ +@ToString +@EqualsAndHashCode +@Index(value = "joinDate", type = IndexType.NON_UNIQUE) +@Index(value = "address", type = IndexType.FULL_TEXT) +@Index(value = "employeeNote.text", type = IndexType.FULL_TEXT) +public class Employee implements Serializable, Mappable { + @Id + @Getter + @Setter + private Long empId; + + @Getter + @Setter + private Date joinDate; + + @Getter + @Setter + private String address; + + @Getter + @Setter + private String emailAddress; + + @Getter + @Setter + private transient Company company; + + @Getter + @Setter + private byte[] blob; + + @Getter + @Setter + private Note employeeNote; + + public Employee() { + } + + public Employee(Employee copy) { + empId = copy.empId; + joinDate = copy.joinDate; + address = copy.address; + company = copy.company; + blob = copy.blob; + employeeNote = copy.employeeNote; + emailAddress = copy.emailAddress; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("empId", empId) + .put("joinDate", joinDate) + .put("address", address) + .put("blob", blob) + .put("emailAddress", emailAddress) + .put("employeeNote", employeeNote != null ? employeeNote.write(mapper) : null); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + empId = document.get("empId", Long.class); + joinDate = document.get("joinDate", Date.class); + address = document.get("address", String.class); + blob = document.get("blob", byte[].class); + emailAddress = document.get("emailAddress", String.class); + + if (document.get("employeeNote") != null) { + employeeNote = new Note(); + employeeNote.read(mapper, document.get("employeeNote", Document.class)); + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/EncryptedPerson.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/EncryptedPerson.java new file mode 100644 index 000000000..8b9d4b23b --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/EncryptedPerson.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Entity; + +import java.util.Date; + +/** + * @author Anindya Chatterjee + */ +@Data +@Entity +public class EncryptedPerson implements Mappable { + private String name; + private String creditCardNumber; + private String cvv; + private Date expiryDate; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name) + .put("creditCardNumber", creditCardNumber) + .put("cvv", cvv) + .put("expiryDate", expiryDate); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + creditCardNumber = document.get("creditCardNumber", String.class); + cvv = document.get("cvv", String.class); + expiryDate = document.get("expiryDate", Date.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Note.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Note.java new file mode 100644 index 000000000..67dc307d1 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/Note.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +import java.io.Serializable; + +/** + * @author Anindya Chatterjee. + */ +@EqualsAndHashCode +public class Note implements Serializable, Mappable { + @Getter + @Setter + private Long noteId; + @Getter + @Setter + private String text; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument().put("noteId", noteId).put("text", text); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + noteId = document.get("noteId", Long.class); + text = document.get("text", String.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ParentClass.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ParentClass.java new file mode 100644 index 000000000..bc2514543 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ParentClass.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +import java.util.Date; + +/** + * @author Anindya Chatterjee + */ +@Getter +@Setter +@Index(value = "date") +public class ParentClass extends SuperDuperClass { + @Id + protected Long id; + private Date date; + + @Override + public Document write(NitriteMapper mapper) { + return super.write(mapper) + .put("id", id) + .put("date", date); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + super.read(mapper, document); + id = document.get("id", Long.class); + date = document.get("date", Date.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/PersonEntity.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/PersonEntity.java new file mode 100644 index 000000000..2b90075fa --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/PersonEntity.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Entity; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +import java.util.Date; +import java.util.UUID; + +/** + * @author Anindya Chatterjee + */ +@Data +@Entity(value = "MyPerson", indices = { + @Index(value = "name", type = IndexType.FULL_TEXT), + @Index(value = "status", type = IndexType.NON_UNIQUE) +}) +public class PersonEntity implements Mappable { + @Id + private String uuid; + private String name; + private String status; + private PersonEntity friend; + private Date dateCreated; + + public PersonEntity() { + this.uuid = UUID.randomUUID().toString(); + this.dateCreated = new Date(); + } + + public PersonEntity(String name) { + this.uuid = UUID.randomUUID().toString(); + this.name = name; + this.dateCreated = new Date(); + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("uuid", uuid) + .put("name", name) + .put("status", status) + .put("friend", friend != null ? friend.write(mapper) : null) + .put("dateCreated", dateCreated); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + if (document != null) { + uuid = document.get("uuid", String.class); + name = document.get("name", String.class); + status = document.get("status", String.class); + dateCreated = document.get("dateCreated", Date.class); + friend = new PersonEntity(); + friend.read(mapper, document.get("friend", Document.class)); + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ProductScore.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ProductScore.java new file mode 100644 index 000000000..65550d182 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/ProductScore.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +/** + * @author Anindya Chatterjee + */ +@Getter +@Setter +public class ProductScore implements Mappable { + private String product; + private int score; + + public ProductScore() { + } + + public ProductScore(String product, int score) { + this.product = product; + this.score = score; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("product", product) + .put("score", score); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + product = document.get("product", String.class); + score = document.get("score", Integer.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/RepeatableIndexTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/RepeatableIndexTest.java new file mode 100644 index 000000000..1ecadb243 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/RepeatableIndexTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Index; + +/** + * @author Anindya Chatterjee + */ +@Data +@Index(value = "firstName") +@Index(value = "age", type = IndexType.NON_UNIQUE) +@Index(value = "lastName", type = IndexType.FULL_TEXT) +public class RepeatableIndexTest implements Mappable { + private String firstName; + private Integer age; + private String lastName; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("firstName", firstName) + .put("age", age) + .put("lastName", lastName); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + firstName = document.get("firstName", String.class); + age = document.get("age", Integer.class); + lastName = document.get("lastName", String.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/StressRecord.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/StressRecord.java new file mode 100644 index 000000000..d1cb199c4 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/StressRecord.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class StressRecord implements Mappable { + private String firstName; + private boolean processed; + private String lastName; + private boolean failed; + private String notes; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument().put("firstName", firstName) + .put("processed", processed) + .put("lastName", lastName) + .put("failed", failed) + .put("notes", notes); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + firstName = document.get("firstName", String.class); + processed = document.get("processed", Boolean.class); + lastName = document.get("lastName", String.class); + failed = document.get("failed", Boolean.class); + notes = document.get("notes", String.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/SubEmployee.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/SubEmployee.java new file mode 100644 index 000000000..8eaa3faf1 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/SubEmployee.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +import java.util.Date; + +/** + * @author Anindya Chatterjee. + */ +@EqualsAndHashCode +public class SubEmployee implements Mappable { + @Getter + @Setter + private Long empId; + + @Getter + @Setter + private Date joinDate; + + @Getter + @Setter + private String address; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("empId", empId) + .put("joinDate", joinDate) + .put("address", address); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + empId = document.get("empId", Long.class); + joinDate = document.get("joinDate", Date.class); + address = document.get("address", String.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/SuperDuperClass.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/SuperDuperClass.java new file mode 100644 index 000000000..198f16d0c --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/SuperDuperClass.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Index; + +/** + * @author Anindya Chatterjee + */ +@Getter +@Setter +@Index(value = "text", type = IndexType.FULL_TEXT) +public class SuperDuperClass implements Mappable { + private String text; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("text", text); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + text = document.get("text", String.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithCircularReference.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithCircularReference.java new file mode 100644 index 000000000..efbb6766a --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithCircularReference.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithCircularReference { + private String name; + private WithCircularReference parent; +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithClassField.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithClassField.java new file mode 100644 index 000000000..79cafe0dc --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithClassField.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithClassField implements Mappable { + @Id + private String name; + private Class clazz; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name) + .put("clazz", clazz); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + clazz = document.get("clazz", Class.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithCustomConstructor.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithCustomConstructor.java new file mode 100644 index 000000000..bea5dabe9 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithCustomConstructor.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithCustomConstructor { + private String name; + private long number; + + public WithCustomConstructor(String name, long number) { + this.name = name; + this.number = number; + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithDateId.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithDateId.java new file mode 100644 index 000000000..229f1aaf7 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithDateId.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +import java.util.Date; + +/** + * @author Anindya Chatterjee + */ +@Getter +@Setter +@EqualsAndHashCode +public class WithDateId implements Mappable { + private Date id; + private String name; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name) + .put("id", id); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + id = document.get("id", Date.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithEmptyStringId.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithEmptyStringId.java new file mode 100644 index 000000000..a0048a6bb --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithEmptyStringId.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithEmptyStringId implements Mappable { + @Id + private String name; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithFinalField.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithFinalField.java new file mode 100644 index 000000000..05afc21e8 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithFinalField.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.exceptions.ObjectMappingException; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +/** + * @author Anindya Chatterjee. + */ +@Getter +public class WithFinalField implements Mappable { + private final long number; + @Setter + private String name; + + public WithFinalField() { + number = 2; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("name", name) + .put("number", number); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + try { + Field field = getClass().getDeclaredField("number"); + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(this, document.get("number", Long.class)); + } catch (Exception e) { + throw new ObjectMappingException("failed to set value"); + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithNitriteId.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithNitriteId.java new file mode 100644 index 000000000..2364be76d --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithNitriteId.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee + */ +@Data +public class WithNitriteId implements Mappable { + @Id + public NitriteId idField; + public String name; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("idField", idField) + .put("name", name); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + idField = document.get("idField", NitriteId.class); + name = document.get("name", String.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithNullId.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithNullId.java new file mode 100644 index 000000000..0dc3fb68b --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithNullId.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithNullId implements Mappable { + @Id + private String name; + private long number; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("name", name) + .put("number", number); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + number = document.get("number", Long.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithObjectId.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithObjectId.java new file mode 100644 index 000000000..5f00f97d4 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithObjectId.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithObjectId implements Mappable { + @Id + private WithOutId withOutId; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("withOutId", withOutId); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + withOutId = document.get("withOutId", WithOutId.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithOutGetterSetter.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithOutGetterSetter.java new file mode 100644 index 000000000..a7a2c56c9 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithOutGetterSetter.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +/** + * @author Anindya Chatterjee. + */ +@EqualsAndHashCode +public class WithOutGetterSetter implements Mappable { + private String name; + private long number; + + public WithOutGetterSetter() { + name = "test"; + number = 2; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name) + .put("number", number); + + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + number = document.get("number", Long.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithOutId.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithOutId.java new file mode 100644 index 000000000..09b63c2c2 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithOutId.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithOutId implements Comparable, Mappable { + private String name; + private long number; + + @Override + public int compareTo(WithOutId o) { + return Long.compare(number, o.number); + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("name", name) + .put("number", number); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + number = document.get("number", Long.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithPrivateConstructor.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithPrivateConstructor.java new file mode 100644 index 000000000..a425209fb --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithPrivateConstructor.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +/** + * @author Anindya Chatterjee. + */ +@EqualsAndHashCode +public class WithPrivateConstructor implements Mappable { + private String name; + private long number; + + private WithPrivateConstructor() { + name = "test"; + number = 2; + } + + public static WithPrivateConstructor create(final String name, final long number) { + WithPrivateConstructor obj = new WithPrivateConstructor(); + obj.number = number; + obj.name = name; + return obj; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name) + .put("number", number); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + number = document.get("number", Long.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithPublicField.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithPublicField.java new file mode 100644 index 000000000..793388231 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithPublicField.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +public class WithPublicField implements Mappable { + @Id + public String name; + public long number; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name) + .put("number", number); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + number = document.get("number", Long.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithTransientField.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithTransientField.java new file mode 100644 index 000000000..9c1ade657 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithTransientField.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithTransientField implements Mappable { + private transient String name; + @Id + private long number; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("number", number); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + number = document.get("number", Long.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithoutEmbeddedId.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithoutEmbeddedId.java new file mode 100644 index 000000000..9ecb9a68b --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/repository/data/WithoutEmbeddedId.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee + */ +@Data +public class WithoutEmbeddedId implements Mappable { + @Id + private NestedId nestedId; + private String data; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("nestedId", nestedId.write(mapper)) + .put("data", data); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + Document nestedId = document.get("nestedId", Document.class); + this.nestedId = mapper.convert(nestedId, NestedId.class); + this.data = document.get("data", String.class); + } + + + @Data + public static class NestedId implements Mappable { + private Long id; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("id", id); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Long.class); + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/rocksdb/NitriteMapStressTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/rocksdb/NitriteMapStressTest.java new file mode 100644 index 000000000..65fe9c1de --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/rocksdb/NitriteMapStressTest.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.rocksdb; + +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.store.NitriteStore; +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; + +import java.util.UUID; + +import static org.dizitart.no2.integration.TestUtil.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * @author Anindya Chatterjee. + */ +public class NitriteMapStressTest { + private final String dbPath = getRandomTempDbFile(); + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Test + public void testWithInsertReadUpdate() { + db = createDb(dbPath); + + NitriteStore nitriteStore = db.getStore(); + NitriteMap nitriteMap = nitriteStore.openMap("testWithInsertReadUpdate", + String.class, Document.class); + + int count = 10000; + for (int i = 0; i < count; i++) { + Document record = Document.createDocument(); + record.put("firstName", UUID.randomUUID().toString()); + record.put("failed", false); + record.put("lastName", UUID.randomUUID().toString()); + record.put("processed", false); + + nitriteMap.put(UUID.randomUUID().toString(), record); + } + + for (Pair entry : nitriteMap.entries()) { + String key = entry.getFirst(); + Document record = entry.getSecond(); + + record.put("processed", true); + + nitriteMap.put(key, record); + } + + db.close(); + } + + @Test + public void testNullKey() { + db = createDb(dbPath); + NitriteStore nitriteStore = db.getStore(); + NitriteMap nitriteMap = nitriteStore.openMap("testNullKey", + String.class, Document.class); + nitriteMap.put(null, Document.createDocument()); + + assertNotNull(nitriteMap.get(null)); + assertEquals(nitriteMap.size(), 1); + + nitriteMap.put(null, Document.createDocument("first", 1)); + assertNotNull(nitriteMap.get(null)); + assertEquals(nitriteMap.size(), 1); + } + + @Test(expected = ValidationException.class) + public void testNullValue() { + db = createDb(dbPath); + NitriteStore nitriteStore = db.getStore(); + NitriteMap nitriteMap = nitriteStore.openMap("testNullValue", + String.class, Document.class); + nitriteMap.put(null, null); + } + + @Test(expected = ValidationException.class) + public void testNullPutIfAbsent() { + db = createDb(dbPath); + NitriteStore nitriteStore = db.getStore(); + NitriteMap nitriteMap = nitriteStore.openMap("testNullPutIfAbsent", + String.class, Document.class); + nitriteMap.putIfAbsent(null, null); + } + + @After + public void tearDown() { + if (db != null && !db.isClosed()) { + db.close(); + } + deleteDb(dbPath); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/rocksdb/NitriteStoreEventTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/rocksdb/NitriteStoreEventTest.java new file mode 100644 index 000000000..d2f977486 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/rocksdb/NitriteStoreEventTest.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.rocksdb; + +import lombok.Data; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.rocksdb.RocksDBModule; +import org.dizitart.no2.store.events.EventInfo; +import org.dizitart.no2.store.events.StoreEventListener; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +import static org.awaitility.Awaitility.await; +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee + */ +public class NitriteStoreEventTest { + private String dbFile; + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void before() { + dbFile = getRandomTempDbFile(); + } + + @After + public void cleanup() throws IOException { + if (db != null && !db.isClosed()) { + db.close(); + } + + deleteDb(dbFile); + } + + @Test + public void testStoreEvents() { + TestStoreEventListener listener = new TestStoreEventListener(); + assertFalse(listener.opened); + assertFalse(listener.committed); + assertFalse(listener.closing); + assertFalse(listener.closed); + + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(dbFile) + .addStoreEventListener(listener) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .openOrCreate(); + + await().atMost(1, TimeUnit.SECONDS).until(() -> listener.opened); + assertTrue(listener.opened); + assertFalse(listener.committed); + assertFalse(listener.closing); + assertFalse(listener.closed); + + db.commit(); + + await().atMost(1, TimeUnit.SECONDS).until(() -> listener.committed); + assertTrue(listener.opened); + assertTrue(listener.committed); + assertFalse(listener.closing); + assertFalse(listener.closed); + + db.close(); + + await().atMost(1, TimeUnit.SECONDS).until(() -> listener.closed); + assertTrue(listener.opened); + assertTrue(listener.committed); + assertTrue(listener.closing); + assertTrue(listener.closed); + + db.getStore().unsubscribe(listener); + } + + @Data + private static class TestStoreEventListener implements StoreEventListener { + private boolean opened; + private boolean committed; + private boolean closing; + private boolean closed; + + @Override + public void onEvent(EventInfo eventInfo) { + switch (eventInfo.getEvent()) { + case Opened: + opened = true; + break; + case Commit: + committed = true; + break; + case Closing: + closing = true; + break; + case Closed: + closed = true; + break; + } + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/stream/DocumentCursorTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/stream/DocumentCursorTest.java new file mode 100644 index 000000000..de377b162 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/stream/DocumentCursorTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.stream; + +import org.dizitart.no2.integration.collection.BaseCollectionTest; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.streams.DocumentStream; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.junit.Test; + +import java.util.Iterator; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee. + */ +public class DocumentCursorTest extends BaseCollectionTest { + + @Test + public void testFindResult() { + NitriteCollection collection = db.getCollection("test"); + collection.insert(createDocument("first", "second")); + + DocumentCursor result = collection.find(); + assertTrue(result instanceof DocumentStream); + } + + @Test(expected = InvalidOperationException.class) + public void testIteratorRemove() { + NitriteCollection collection = db.getCollection("test"); + collection.insert(createDocument("first", "second")); + + DocumentCursor cursor = collection.find(); + Iterator iterator = cursor.iterator(); + if (iterator.hasNext()) { + iterator.next(); + iterator.remove(); + } + } + + @Test + public void testValidateProjection() { + NitriteCollection collection = db.getCollection("test"); + collection.insert(createDocument("first", "second")); + + Document projection = createDocument("first", createDocument("second", null)); + RecordStream project = collection.find().project(projection); + assertNotNull(project); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/stream/JoinedDocumentStreamTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/stream/JoinedDocumentStreamTest.java new file mode 100644 index 000000000..00923c738 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/stream/JoinedDocumentStreamTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.stream; + +import org.dizitart.no2.integration.collection.BaseCollectionTest; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.Lookup; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.streams.JoinedDocumentStream; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.junit.Test; + +import java.util.Iterator; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee + */ +public class JoinedDocumentStreamTest extends BaseCollectionTest { + + @Test + public void testFindResult() { + NitriteCollection collection = db.getCollection("test"); + collection.insert(createDocument("first", "second")); + + RecordStream result = collection.find().join(collection.find(), new Lookup()); + assertTrue(result instanceof JoinedDocumentStream); + } + + @Test(expected = InvalidOperationException.class) + public void testIteratorRemove() { + NitriteCollection collection = db.getCollection("test"); + collection.insert(createDocument("first", "second")); + + RecordStream cursor = collection.find().join(collection.find(), new Lookup()); + assertNotNull(cursor.toString()); + Iterator iterator = cursor.iterator(); + if (iterator.hasNext()) { + iterator.next(); + iterator.remove(); + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/transaction/TransactionCollectionTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/transaction/TransactionCollectionTest.java new file mode 100644 index 000000000..05a2b095b --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/transaction/TransactionCollectionTest.java @@ -0,0 +1,791 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.transaction; + +import com.github.javafaker.Faker; +import org.dizitart.no2.integration.collection.BaseCollectionTest; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.meta.Attributes; +import org.dizitart.no2.exceptions.NitriteIOException; +import org.dizitart.no2.exceptions.TransactionException; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.transaction.Session; +import org.dizitart.no2.transaction.Transaction; +import org.junit.Test; + +import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.collection.UpdateOptions.updateOptions; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class TransactionCollectionTest extends BaseCollectionTest { + + @Test + public void testCommitInsert() { + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + + Document document = createDocument("firstName", "John"); + txCol.insert(document); + + assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); + assertNotEquals(collection.find(where("firstName").eq("John")).size(), 1); + + transaction.commit(); + + assertEquals(collection.find(where("firstName").eq("John")).size(), 1); + } + } + } + + @Test + public void testRollbackInsert() { + collection.createIndex("firstName"); + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + + NitriteCollection txCol = transaction.getCollection("test"); + + Document document = createDocument("firstName", "John"); + Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); + txCol.insert(document); + txCol.insert(document2); + + // just to create UniqueConstraintViolation for rollback + collection.insert(createDocument("firstName", "Jane")); + + assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); + assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertNotEquals(collection.find(where("firstName").eq("John")).size(), 1); + assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + } + } + } + + @Test + public void testCommitUpdate() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + document.put("lastName", "Doe"); + + txCol.update(where("firstName").eq("John"), document, updateOptions(true)); + + assertEquals(txCol.find(where("lastName").eq("Doe")).size(), 1); + assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + + transaction.commit(); + + assertEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + } + } + } + + @Test + public void testRollbackUpdate() { + collection.createIndex("firstName"); + collection.insert(createDocument("firstName", "Jane")); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + + NitriteCollection txCol = transaction.getCollection("test"); + + Document document = createDocument("firstName", "John"); + Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); + txCol.update(where("firstName").eq("Jane"), document2); + txCol.insert(document); + + // just to create UniqueConstraintViolation for rollback + collection.insert(createDocument("firstName", "John")); + + assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); + assertEquals(txCol.find(where("lastName").eq("Doe")).size(), 1); + assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(collection.find(where("firstName").eq("Jane")).size(), 1); + assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + } + } + } + + @Test + public void testCommitRemove() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + + txCol.remove(where("firstName").eq("John")); + + assertEquals(txCol.find(where("firstName").eq("John")).size(), 0); + assertEquals(collection.find(where("firstName").eq("John")).size(), 1); + + transaction.commit(); + + assertEquals(collection.find(where("firstName").eq("John")).size(), 0); + } + } + } + + @Test + public void testRollbackRemove() { + collection.createIndex("firstName"); + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + NitriteCollection txCol = transaction.getCollection("test"); + + txCol.remove(where("firstName").eq("John")); + + assertEquals(txCol.find(where("firstName").eq("John")).size(), 0); + assertEquals(collection.find(where("firstName").eq("John")).size(), 1); + + txCol.insert(createDocument("firstName", "Jane")); + collection.insert(createDocument("firstName", "Jane")); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(collection.find(where("firstName").eq("John")).size(), 1); + assertEquals(collection.find(where("firstName").eq("Jane")).size(), 1); + } + } + } + + @Test + public void testCommitCreateIndex() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + txCol.createIndex(indexOptions(IndexType.FULL_TEXT), "firstName"); + + assertTrue(txCol.hasIndex("firstName")); + assertFalse(collection.hasIndex("firstName")); + + transaction.commit(); + + assertTrue(collection.hasIndex("firstName")); + } + } + } + + @Test + public void testRollbackCreateIndex() { + Document document = createDocument("firstName", "John"); + Document document2 = createDocument("firstName", "Jane"); + collection.insert(document); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + NitriteCollection txCol = transaction.getCollection("test"); + + txCol.createIndex("firstName"); + + assertTrue(txCol.hasIndex("firstName")); + assertFalse(collection.hasIndex("firstName")); + + txCol.insert(document2); + collection.insert(document2); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertFalse(collection.hasIndex("firstName")); + } + } + } + + @Test + public void testCommitClear() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + txCol.clear(); + + assertEquals(0, txCol.size()); + assertEquals(1, collection.size()); + + transaction.commit(); + + assertEquals(0, collection.size()); + } + } + } + + @Test + public void testRollbackClear() { + collection.createIndex("firstName"); + Document document = createDocument("firstName", "John"); + Document document2 = createDocument("firstName", "Jane"); + collection.insert(document); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + NitriteCollection txCol = transaction.getCollection("test"); + + txCol.clear(); + + assertEquals(0, txCol.size()); + assertEquals(1, collection.size()); + + txCol.insert(document2); + collection.insert(document2); + + throw new TransactionException("failed"); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(2, collection.size()); + } + } + } + + @Test + public void testCommitDropIndex() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + collection.createIndex("firstName"); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + txCol.dropIndex("firstName"); + + assertFalse(txCol.hasIndex("firstName")); + assertTrue(collection.hasIndex("firstName")); + + transaction.commit(); + + assertFalse(collection.hasIndex("firstName")); + } + } + } + + @Test + public void testRollbackDropIndex() { + Document document = createDocument("firstName", "John").put("lastName", "Doe"); + Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); + collection.insert(document); + collection.createIndex("firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + NitriteCollection txCol = transaction.getCollection("test"); + txCol.dropIndex("lastName"); + + assertFalse(txCol.hasIndex("lastName")); + assertTrue(collection.hasIndex("lastName")); + + txCol.insert(document2); + collection.insert(document2); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertTrue(collection.hasIndex("lastName")); + } + } + } + + @Test + public void testCommitDropAllIndices() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + collection.createIndex("firstName"); + collection.createIndex("lastName"); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + txCol.dropAllIndices(); + + assertFalse(txCol.hasIndex("firstName")); + assertFalse(txCol.hasIndex("lastName")); + assertTrue(collection.hasIndex("firstName")); + assertTrue(collection.hasIndex("lastName")); + + transaction.commit(); + + assertFalse(collection.hasIndex("firstName")); + assertFalse(collection.hasIndex("lastName")); + } + } + } + + @Test + public void testRollbackDropAllIndices() { + Document document = createDocument("firstName", "John").put("lastName", "Doe"); + collection.insert(document); + collection.createIndex("firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + NitriteCollection txCol = transaction.getCollection("test"); + txCol.dropAllIndices(); + + assertFalse(txCol.hasIndex("firstName")); + assertFalse(txCol.hasIndex("lastName")); + assertTrue(collection.hasIndex("firstName")); + assertTrue(collection.hasIndex("lastName")); + + txCol.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); + collection.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); + + throw new TransactionException("failed"); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertTrue(collection.hasIndex("firstName")); + assertTrue(collection.hasIndex("lastName")); + } + } + } + + @Test + public void testCommitDropCollection() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + txCol.drop(); + + boolean expectedException = false; + try { + assertEquals(0, txCol.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + assertEquals(1, collection.size()); + + transaction.commit(); + + expectedException = false; + try { + assertEquals(0, collection.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + } + } + } + + @Test + public void testRollbackDropCollection() { + collection.createIndex("firstName"); + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + NitriteCollection txCol = transaction.getCollection("test"); + + txCol.drop(); + + boolean expectedException = false; + try { + assertEquals(0, txCol.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + assertEquals(1, collection.size()); + + throw new TransactionException("failed"); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(1, collection.size()); + } + } + } + + @Test + public void testCommitSetAttribute() { + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + + Attributes attributes = new Attributes(); + Map hashMap = new HashMap<>(); + hashMap.put("key", "value"); + attributes.setAttributes(hashMap); + txCol.setAttributes(attributes); + + assertNull(collection.getAttributes()); + + transaction.commit(); + + assertEquals("value", collection.getAttributes().get("key")); + } + } + } + + @Test + public void testRollbackSetAttribute() { + collection.createIndex("firstName"); + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + + NitriteCollection txCol = transaction.getCollection("test"); + + Attributes attributes = new Attributes(); + Map map = new HashMap<>(); + map.put("key", "value"); + attributes.setAttributes(map); + txCol.setAttributes(attributes); + + txCol.insert(createDocument("firstName", "John")); + txCol.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); + + assertNull(collection.getAttributes()); + + // just to create UniqueConstraintViolation for rollback + collection.insert(createDocument("firstName", "Jane")); + + assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); + assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertNull(collection.getAttributes().get("key")); + } + } + } + + @Test + public void testConcurrentInsertAndRemove() { + NitriteCollection collection = db.getCollection("test"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "firstName"); + collection.createIndex("id"); + Faker faker = new Faker(); + List> futures = new ArrayList<>(); + + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + final long fi = i; + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + NitriteCollection txCol = transaction.getCollection("test"); + + for (int j = 0; j < 10; j++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("lastName", faker.name().lastName()) + .put("id", j + (fi * 10)); + txCol.insert(document); + } + + txCol.remove(where("id").eq(2 + (fi * 10))); + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(90, collection.size()); + } + } + + @Test + public void testConcurrentInsert() { + NitriteCollection collection = db.getCollection("test"); + Faker faker = new Faker(); + List> futures = new ArrayList<>(); + + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + NitriteCollection txCol = transaction.getCollection("test"); + + for (int j = 0; j < 10; j++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("lastName", faker.name().lastName()); + txCol.insert(document); + } + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(100, collection.size()); + } + } + + @Test + public void testConcurrentUpdate() { + NitriteCollection collection = db.getCollection("test"); + for (int i = 0; i < 10; i++) { + Document document = createDocument("id", i); + collection.insert(document); + } + + Faker faker = new Faker(); + List> futures = new ArrayList<>(); + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + NitriteCollection txCol = transaction.getCollection("test"); + + for (int j = 0; j < 10; j++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("lastName", faker.name().lastName()) + .put("id", j); + txCol.update(where("id").eq(j), document, updateOptions(true)); + } + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(10, collection.size()); + } + } + + @Test + public void testTransactionOnDifferentCollections() { + NitriteCollection col1 = db.getCollection("test1"); + NitriteCollection col2 = db.getCollection("test2"); + NitriteCollection col3 = db.getCollection("test3"); + col3.createIndex("id"); + + Faker faker = new Faker(); + + try(Session session = db.createSession()) { + Transaction transaction = session.beginTransaction(); + + NitriteCollection test1 = transaction.getCollection("test1"); + NitriteCollection test2 = transaction.getCollection("test2"); + NitriteCollection test3 = transaction.getCollection("test3"); + + for (int i = 0; i < 10; i++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", i); + test1.insert(document); + + document = createDocument("firstName", faker.name().firstName()) + .put("id", i + 10); + test2.insert(document); + + document = createDocument("firstName", faker.name().firstName()) + .put("id", i + 20); + test3.insert(document); + } + + assertEquals(test1.size(), 10); + assertEquals(test2.size(), 10); + assertEquals(test3.size(), 10); + + assertEquals(col1.size(), 0); + assertEquals(col2.size(), 0); + assertEquals(col3.size(), 0); + + transaction.commit(); + + assertEquals(col1.size(), 10); + assertEquals(col2.size(), 10); + assertEquals(col3.size(), 10); + } + + + Transaction transaction = null; + try (Session session = db.createSession()) { + transaction = session.beginTransaction(); + + NitriteCollection test1 = transaction.getCollection("test1"); + NitriteCollection test2 = transaction.getCollection("test2"); + NitriteCollection test3 = transaction.getCollection("test3"); + + for (int i = 0; i < 10; i++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", i + 30); + test1.insert(document); + + document = createDocument("firstName", faker.name().firstName()) + .put("id", i + 40); + test2.insert(document); + + document = createDocument("firstName", faker.name().firstName()) + .put("id", i + 50); + test3.insert(document); + } + + assertEquals(test1.size(), 20); + assertEquals(test2.size(), 20); + assertEquals(test3.size(), 20); + + assertEquals(col1.size(), 10); + assertEquals(col2.size(), 10); + assertEquals(col3.size(), 10); + + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", 52); + col3.insert(document); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + + assertEquals(col1.size(), 10); + assertEquals(col2.size(), 10); + assertEquals(col3.size(), 11); // last document added + } + } + + @Test(expected = TransactionException.class) + public void testFailureOnClosedTransaction() { + try(Session session = db.createSession()) { + Transaction transaction = session.beginTransaction(); + NitriteCollection col = transaction.getCollection("test"); + col.insert(createDocument("id", 1)); + transaction.commit(); + + col.insert(createDocument("id", 2)); + fail(); + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/transaction/TransactionRepositoryTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/transaction/TransactionRepositoryTest.java new file mode 100644 index 000000000..5e93303ed --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/transaction/TransactionRepositoryTest.java @@ -0,0 +1,829 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.transaction; + +import com.github.javafaker.Faker; +import org.dizitart.no2.integration.repository.BaseObjectRepositoryTest; +import org.dizitart.no2.integration.repository.data.SubEmployee; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.meta.Attributes; +import org.dizitart.no2.exceptions.NitriteIOException; +import org.dizitart.no2.exceptions.TransactionException; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.transaction.Session; +import org.dizitart.no2.transaction.Transaction; +import org.junit.Test; + +import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class TransactionRepositoryTest extends BaseObjectRepositoryTest { + + @Test + public void testCommitInsert() { + ObjectRepository repository = db.getRepository(TxData.class); + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + TxData txData1 = new TxData(); + txData1.setId(1L); + txData1.setName("John"); + + txRepo.insert(txData1); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 1); + assertNotEquals(repository.find(where("name").eq("John")).size(), 1); + + transaction.commit(); + + assertEquals(repository.find(where("name").eq("John")).size(), 1); + } + } + } + + @Test + public void testRollbackInsert() { + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + TxData txData1 = new TxData(); + txData1.setId(1L); + txData1.setName("John"); + + TxData txData2 = new TxData(); + txData2.setId(2L); + txData2.setName("Jane"); + + txRepo.insert(txData1, txData2); + + txData2.setName("Molly"); + repository.insert(txData2); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 1); + assertEquals(repository.find(where("name").eq("John")).size(), 0); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(repository.find(where("name").eq("John")).size(), 0); + assertEquals(repository.find(where("name").eq("Molly")).size(), 1); + } + } + } + + @Test + public void testCommitUpdate() { + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(new TxData(1L, "John")); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + TxData txData1 = new TxData(1L, "Jane"); + txRepo.update(txData1, true); + + assertEquals(txRepo.find(where("name").eq("Jane")).size(), 1); + assertNotEquals(repository.find(where("name").eq("Jane")).size(), 1); + + transaction.commit(); + + assertEquals(repository.find(where("name").eq("Jane")).size(), 1); + } + } + } + + @Test + public void testRollbackUpdate() { + ObjectRepository repository = db.getRepository(TxData.class, "rollback"); + repository.createIndex("name"); + repository.insert(new TxData(1L, "Jane")); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + + ObjectRepository txRepo = transaction.getRepository(TxData.class, "rollback"); + + TxData txData1 = new TxData(); + txData1.setId(2L); + txData1.setName("John"); + + TxData txData2 = new TxData(); + txData2.setId(1L); + txData2.setName("Jane Doe"); + txRepo.update(txData2); + txRepo.insert(txData1); + + // just to create UniqueConstraintViolation for rollback + repository.insert(txData1); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 1); + assertEquals(txRepo.find(where("name").eq("Jane Doe")).size(), 1); + assertNotEquals(repository.find(where("name").eq("Jane Doe")).size(), 1); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(repository.find(where("name").eq("Jane")).size(), 1); + assertNotEquals(repository.find(where("name").eq("Jane Doe")).size(), 1); + } + } + } + + @Test + public void testCommitRemove() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + txRepo.remove(where("name").eq("John")); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 0); + assertEquals(repository.find(where("name").eq("John")).size(), 1); + + transaction.commit(); + + assertEquals(repository.find(where("name").eq("John")).size(), 0); + } + } + } + + @Test + public void testRollbackRemove() { + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + TxData txData1 = new TxData(1L, "John"); + repository.insert(txData1); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + txRepo.remove(where("name").eq("John")); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 0); + assertEquals(repository.find(where("name").eq("John")).size(), 1); + + TxData txData2 = new TxData(2L, "Jane"); + txRepo.insert(txData2); + repository.insert(txData2); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(repository.find(where("name").eq("John")).size(), 1); + assertEquals(repository.find(where("name").eq("Jane")).size(), 1); + } + } + } + + @Test + public void testCommitCreateIndex() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.createIndex(indexOptions(IndexType.FULL_TEXT), "name"); + + assertTrue(txRepo.hasIndex("name")); + assertFalse(repository.hasIndex("name")); + + transaction.commit(); + + assertTrue(repository.hasIndex("name")); + } + } + } + + @Test + public void testRollbackCreateIndex() { + TxData txData1 = new TxData(1L, "John"); + TxData txData2 = new TxData(2L, "Jane"); + + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(txData1); + + try(Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.createIndex(indexOptions(IndexType.FULL_TEXT), "name"); + + assertTrue(txRepo.hasIndex("name")); + assertFalse(repository.hasIndex("name")); + + txRepo.insert(txData2); + repository.insert(txData2); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertFalse(repository.hasIndex("name")); + } + } + } + + @Test + public void testCommitClear() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.clear(); + + assertEquals(0, txRepo.size()); + assertEquals(1, repository.size()); + + transaction.commit(); + + assertEquals(0, repository.size()); + } + } + } + + @Test + public void testRollbackClear() { + TxData txData1 = new TxData(1L, "John"); + TxData txData2 = new TxData(2L, "Jane"); + + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try(Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.clear(); + + assertEquals(0, txRepo.size()); + assertEquals(1, repository.size()); + + txRepo.insert(txData2); + repository.insert(txData2); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(2, repository.size()); + } + } + } + + @Test + public void testCommitDropIndex() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.dropIndex("name"); + + assertFalse(txRepo.hasIndex("name")); + assertTrue(repository.hasIndex("name")); + + transaction.commit(); + + assertFalse(repository.hasIndex("name")); + } + } + } + + @Test + public void testRollbackDropIndex() { + TxData txData1 = new TxData(1L, "John"); + TxData txData2 = new TxData(2L, "Jane"); + + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try(Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.dropIndex("name"); + + assertFalse(txRepo.hasIndex("name")); + assertTrue(repository.hasIndex("name")); + + txRepo.insert(txData2); + repository.insert(txData2); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertTrue(repository.hasIndex("name")); + } + } + } + + @Test + public void testCommitDropAllIndices() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.dropAllIndices(); + + assertFalse(txRepo.hasIndex("name")); + assertTrue(repository.hasIndex("name")); + + transaction.commit(); + + assertFalse(repository.hasIndex("name")); + } + } + } + + @Test + public void testRollbackDropAllIndices() { + TxData txData1 = new TxData(1L, "John"); + TxData txData2 = new TxData(2L, "Jane"); + + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try(Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.dropAllIndices(); + + assertFalse(txRepo.hasIndex("name")); + assertTrue(repository.hasIndex("name")); + + txRepo.insert(txData2); + repository.insert(txData2); + + throw new TransactionException("failed"); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertTrue(repository.hasIndex("name")); + } + } + } + + @Test + public void testCommitDropRepository() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.drop(); + + boolean expectedException = false; + try { + assertEquals(0, txRepo.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + assertEquals(1, repository.size()); + + transaction.commit(); + + expectedException = false; + try { + assertEquals(0, repository.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + } + } + } + + @Test + public void testRollbackDropRepository() { + TxData txData1 = new TxData(1L, "John"); + + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try(Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.drop(); + + boolean expectedException = false; + try { + assertEquals(0, txRepo.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + assertEquals(1, repository.size()); + + throw new TransactionException("failed"); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(1, repository.size()); + } + } + } + + @Test + public void testCommitSetAttribute() { + ObjectRepository repository = db.getRepository(TxData.class); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + Attributes attributes = new Attributes(); + Map hashMap = new HashMap<>(); + hashMap.put("key", "value"); + attributes.setAttributes(hashMap); + txRepo.setAttributes(attributes); + + assertNull(repository.getAttributes()); + + transaction.commit(); + + assertEquals("value", repository.getAttributes().get("key")); + } + } + } + + @Test + public void testRollbackSetAttribute() { + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + Attributes attributes = new Attributes(); + Map map = new HashMap<>(); + map.put("key", "value"); + attributes.setAttributes(map); + txRepo.setAttributes(attributes); + + txRepo.insert(new TxData(1L, "John")); + txRepo.insert(new TxData(2L, "Jane")); + + assertNull(repository.getAttributes()); + + // just to create UniqueConstraintViolation for rollback + repository.insert(new TxData(2L, "Jane")); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 1); + assertNotEquals(repository.find(where("name").eq("John")).size(), 1); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertNull(repository.getAttributes().get("key")); + } + } + } + + @Test + public void testConcurrentInsertAndRemove() { + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex(indexOptions(IndexType.NON_UNIQUE), "name"); + Faker faker = new Faker(); + List> futures = new ArrayList<>(); + + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + final long fi = i; + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + for (long j = 0; j < 10; j++) { + TxData txData = new TxData(j + (fi * 10), faker.name().name()); + txRepo.insert(txData); + } + + txRepo.remove(where("id").eq(2L + (fi * 10))); + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(90, repository.size()); + } + } + + @Test + public void testConcurrentInsert() { + ObjectRepository repository = db.getRepository(TxData.class); + Faker faker = new Faker(); + List> futures = new ArrayList<>(); + + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + final long fi = i; + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + for (long j = 0; j < 10; j++) { + TxData txData = new TxData(j + (fi * 10), faker.name().name()); + txRepo.insert(txData); + } + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(100, repository.size()); + } + } + + @Test + public void testConcurrentUpdate() { + ObjectRepository repository = db.getRepository(TxData.class); + Faker faker = new Faker(); + for (long j = 0; j < 10; j++) { + TxData txData = new TxData(j, faker.name().name()); + repository.insert(txData); + } + + List> futures = new ArrayList<>(); + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + for (int j = 0; j < 10; j++) { + TxData txData = new TxData((long) j, faker.name().name()); + txRepo.update(where("id").eq(j), txData); + } + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(10, repository.size()); + } + } + + @Test + public void testTransactionOnDifferentRepositoriesAndCollections() { + ObjectRepository repo1 = db.getRepository(TxData.class); + ObjectRepository repo2 = db.getRepository(TxData.class, "2"); + ObjectRepository repo3 = db.getRepository(SubEmployee.class); + NitriteCollection col1 = db.getCollection("test1"); + col1.createIndex("id"); + + Faker faker = new Faker(); + + try(Session session = db.createSession()) { + Transaction transaction = session.beginTransaction(); + + ObjectRepository txRepo1 = transaction.getRepository(TxData.class); + ObjectRepository txRepo2 = transaction.getRepository(TxData.class, "2"); + ObjectRepository txRepo3 = transaction.getRepository(SubEmployee.class); + NitriteCollection test1 = transaction.getCollection("test1"); + + for (long i = 0; i < 10; i++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", i); + test1.insert(document); + + TxData txData1 = new TxData(i, faker.name().name()); + txRepo1.insert(txData1); + + TxData txData2 = new TxData(i + 10, faker.name().name()); + txRepo2.insert(txData2); + + SubEmployee employee = new SubEmployee(); + employee.setAddress(faker.address().fullAddress()); + employee.setEmpId(i); + employee.setJoinDate(faker.date().birthday()); + txRepo3.insert(employee); + } + + assertEquals(test1.size(), 10); + assertEquals(txRepo1.size(), 10); + assertEquals(txRepo2.size(), 10); + assertEquals(txRepo3.size(), 10); + + assertEquals(col1.size(), 0); + assertEquals(repo1.size(), 0); + assertEquals(repo2.size(), 0); + assertEquals(repo3.size(), 0); + + transaction.commit(); + + assertEquals(col1.size(), 10); + assertEquals(repo1.size(), 10); + assertEquals(repo2.size(), 10); + assertEquals(repo3.size(), 10); + } + + Transaction transaction = null; + try (Session session = db.createSession()) { + transaction = session.beginTransaction(); + + ObjectRepository txRepo1 = transaction.getRepository(TxData.class); + ObjectRepository txRepo2 = transaction.getRepository(TxData.class, "2"); + ObjectRepository txRepo3 = transaction.getRepository(SubEmployee.class); + NitriteCollection test1 = transaction.getCollection("test1"); + + for (long i = 0; i < 10; i++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", i + 10); + test1.insert(document); + + TxData txData1 = new TxData(i + 10, faker.name().name()); + txRepo1.insert(txData1); + + TxData txData2 = new TxData(i + 20, faker.name().name()); + txRepo2.insert(txData2); + + SubEmployee employee = new SubEmployee(); + employee.setAddress(faker.address().fullAddress()); + employee.setEmpId(i + 10); + employee.setJoinDate(faker.date().birthday()); + txRepo3.insert(employee); + } + + assertEquals(test1.size(), 20); + assertEquals(txRepo1.size(), 20); + assertEquals(txRepo2.size(), 20); + assertEquals(txRepo3.size(), 20); + + assertEquals(col1.size(), 10); + assertEquals(repo1.size(), 10); + assertEquals(repo2.size(), 10); + assertEquals(repo3.size(), 10); + + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", 12L); + col1.insert(document); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + + assertEquals(col1.size(), 11); // last doc added + assertEquals(repo1.size(), 10); + assertEquals(repo2.size(), 10); + assertEquals(repo3.size(), 10); + } + } + + @Test(expected = TransactionException.class) + public void testFailureOnClosedTransaction() { + try(Session session = db.createSession()) { + Transaction transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.insert(new TxData(1L, "John")); + transaction.commit(); + + txRepo.insert(new TxData(2L, "Jane")); + fail(); + } + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/transaction/TxData.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/transaction/TxData.java new file mode 100644 index 000000000..1e5ed7ca6 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/integration/transaction/TxData.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.transaction; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +class TxData implements Mappable { + @Id + private Long id; + private String name; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("id", id) + .put("name", name); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Long.class); + name = document.get("name", String.class); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/AbstractTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/AbstractTest.java deleted file mode 100644 index 4e9760a56..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/AbstractTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2019-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb; - -import org.dizitart.no2.Nitrite; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; - -import java.io.IOException; -import java.text.ParseException; - -/** - * @author Anindya Chatterjee - */ -public abstract class AbstractTest { - protected final String fileName = DbTestOperations.getRandomTempDbFile(); - protected Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() throws ParseException { - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(fileName) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(); - } - - @After - public void cleanUp() throws IOException { - if (db != null && !db.isClosed()) { - db.close(); - } - TestUtil.deleteFile(fileName); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/BaseCollectionTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/BaseCollectionTest.java deleted file mode 100644 index f91a7bf55..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/BaseCollectionTest.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb; - -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.io.FileUtils; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.rocksdb.formatter.KryoObjectFormatter; -import org.dizitart.no2.rocksdb.serializers.JodaTimeKryoKeySerializer; -import org.joda.time.DateTime; -import org.junit.After; -import org.junit.Before; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.io.File; -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Collection; -import java.util.Locale; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.rocksdb.DbTestOperations.getRandomTempDbFile; - -@Slf4j -@RunWith(value = Parameterized.class) -public abstract class BaseCollectionTest { - @Parameterized.Parameter - public boolean isSecured = false; - - protected Nitrite db; - protected NitriteCollection collection; - protected Document doc1, doc2, doc3; - protected SimpleDateFormat simpleDateFormat; - private final String fileName = getRandomTempDbFile(); - protected final KryoObjectFormatter fstMarshaller = new KryoObjectFormatter(); - - @Parameterized.Parameters(name = "Secured = {0}") - public static Collection data() { - return Arrays.asList(new Object[][]{ - {false}, - {true}, - }); - } - -// @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - try { - openDb(); - - simpleDateFormat - = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); - - doc1 = createDocument("firstName", "fn1") - .put("lastName", "ln1") - .put("birthDay", simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) - .put("data", new byte[]{1, 2, 3}) - .put("list", Arrays.asList("one", "two", "three")) - .put("body", "a quick brown fox jump over the lazy dog"); - doc2 = createDocument("firstName", "fn2") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2010-06-12T16:02:48.440Z")) - .put("data", new byte[]{3, 4, 3}) - .put("list", Arrays.asList("three", "four", "three")) - .put("body", "quick hello world from nitrite"); - doc3 = createDocument("firstName", "fn3") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2014-04-17T16:02:48.440Z")) - .put("data", new byte[]{9, 4, 8}) - .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + - "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); - - collection = db.getCollection("test"); - collection.remove(ALL); - } catch (Throwable t) { - log.error("Error while initializing test database", t); - } - } - - @After - public void clear() { - try { - if (collection != null && !collection.isDropped()) { - collection.close(); - } - if (db != null && !db.isClosed()) db.close(); - FileUtils.deleteDirectory(new File(fileName)); - } catch (Throwable t) { - log.error("Error while clearing test database", t); - } - } - - private void openDb() { - fstMarshaller.registerSerializer(DateTime.class, new JodaTimeKryoKeySerializer()); - - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(fileName) - .objectFormatter(fstMarshaller) - .build(); - - if (isSecured) { - db = Nitrite.builder() - .fieldSeparator(".") - .loadModule(storeModule) - .openOrCreate("test-user", "test-password"); - } else { - db = Nitrite.builder() - .fieldSeparator(".") - .loadModule(storeModule) - .openOrCreate(); - } - } - - protected WriteResult insert() { - return collection.insert(doc1, doc2, doc3); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/CollectionFactoryTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/CollectionFactoryTest.java new file mode 100644 index 000000000..f8eb46ab3 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/CollectionFactoryTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.rocksdb; + +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.collection.CollectionFactory; +import org.dizitart.no2.common.concurrent.LockService; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.integration.Retry; +import org.junit.Rule; +import org.junit.Test; + +import static org.junit.Assert.assertNotNull; + +/** + * @author Anindya Chatterjee + */ +public class CollectionFactoryTest { + + @Rule + public Retry retry = new Retry(3); + + @Test(expected = ValidationException.class) + public void testGetCollectionMapStoreNull() { + CollectionFactory factory = new CollectionFactory(new LockService()); + assertNotNull(factory); + + NitriteConfig config = new NitriteConfig(); + factory.getCollection(null, config, true); + } + + @Test(expected = ValidationException.class) + public void testGetCollectionContextNull() { + CollectionFactory factory = new CollectionFactory(new LockService()); + factory.getCollection("test", null, false); + } +} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/CollectionFieldIndexTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/CollectionFieldIndexTest.java deleted file mode 100644 index 76dc2edd4..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/CollectionFieldIndexTest.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.index.IndexType; -import org.junit.Test; - -import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee - */ -public class CollectionFieldIndexTest extends AbstractTest { - - @Test - public void testCollection() { - Document doc1 = Document.createDocument("name", "Anindya") - .put("color", new String[]{"red", "green", "blue"}) - .put("books", new Document[]{ - Document.createDocument("name", "Book ABCD") - .put("tag", new String[]{"tag1", "tag2"}), - Document.createDocument("name", "Book EFGH") - .put("tag", new String[]{"tag3", "tag1"}), - Document.createDocument("name", "No Tag") - }); - - Document doc2 = Document.createDocument("name", "Bill") - .put("color", new String[]{"purple", "yellow", "gray"}) - .put("books", new Document[]{ - Document.createDocument("name", "Book abcd") - .put("tag", new String[]{"tag4", "tag5"}), - Document.createDocument("name", "Book wxyz") - .put("tag", new String[]{"tag3", "tag1"}), - Document.createDocument("name", "No Tag 2") - }); - - Document doc3 = Document.createDocument("name", "John") - .put("color", new String[]{"black", "sky", "violet"}) - .put("books", new Document[]{ - Document.createDocument("name", "Book Mnop") - .put("tag", new String[]{"tag6", "tag2"}), - Document.createDocument("name", "Book ghij") - .put("tag", new String[]{"tag3", "tag7"}), - Document.createDocument("name", "No Tag") - }); - - NitriteCollection collection = db.getCollection("test"); - collection.createIndex("color", indexOptions(IndexType.Unique)); - collection.createIndex("books.tag", indexOptions(IndexType.NonUnique)); - collection.createIndex("books.name", indexOptions(IndexType.Fulltext)); - - WriteResult writeResult = collection.insert(doc1, doc2, doc3); - assertEquals(writeResult.getAffectedCount(), 3); - - DocumentCursor documents = collection.find(where("color").eq("red")); - assertTrue(isSimilar(documents.firstOrNull(), doc1, "name", "color", "books")); - - documents = collection.find(where("books.name").text("abcd")); - assertEquals(documents.size(), 2); - - documents = collection.find(where("books.tag").eq("tag2")); - assertEquals(documents.size(), 2); - - documents = collection.find(where("books.tag").eq("tag5")); - assertEquals(documents.size(), 1); - - documents = collection.find(where("books.tag").eq("tag10")); - assertEquals(documents.size(), 0); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/CustomFilterTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/CustomFilterTest.java deleted file mode 100644 index 6e905a7a2..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/CustomFilterTest.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb; - -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.index.IndexType; -import org.junit.Test; - -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class CustomFilterTest extends BaseCollectionTest { - - @Test - public void testCustomFilter() { - insert(); - collection.createIndex("firstName", indexOptions(IndexType.NonUnique)); - DocumentCursor cursor = collection.find(element -> element.getSecond().get("firstName", String.class) - .equalsIgnoreCase("FN1")); - - assertEquals(cursor.size(), 1); - assertEquals(cursor.firstOrNull().get("firstName"), "fn1"); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/DbTestOperations.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/DbTestOperations.java deleted file mode 100644 index 11cfeb258..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/DbTestOperations.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.index.IndexType; - -import java.io.File; -import java.io.IOException; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.*; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee. - */ -public class DbTestOperations { - private Nitrite db; - private final String fileName = getRandomTempDbFile(); - - public static String getRandomTempDbFile() { - String dataDir = System.getProperty("java.io.tmpdir") + File.separator + "nitrite" + File.separator + "data"; - File file = new File(dataDir); - if (!file.exists()) { - assertTrue(file.mkdirs()); - } - return file.getPath() + File.separator + UUID.randomUUID().toString() + ".db"; - } - - void createDb() { - db = TestUtil.createDb(fileName); - db.close(); - } - - void writeCollection() { - NitriteCollection collection; - - db = TestUtil.createDb(fileName); - - collection = db.getCollection("test"); - collection.remove(ALL); - db.close(); - } - - void writeIndex() { - NitriteCollection collection; - - db = TestUtil.createDb(fileName); - - collection = db.getCollection("test"); - collection.remove(ALL); - collection.createIndex("body", indexOptions(IndexType.Fulltext)); - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - db.close(); - } - - void insertInCollection() throws ParseException { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); - - Document doc1 = createDocument("firstName", "fn1") - .put("lastName", "ln1") - .put("birthDay", simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) - .put("data", new byte[]{1, 2, 3}) - .put("body", "a quick brown fox jump over the lazy dog"); - Document doc2 = createDocument("firstName", "fn2") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2010-06-12T16:02:48.440Z")) - .put("data", new byte[]{3, 4, 3}) - .put("body", "quick hello world from nitrite"); - Document doc3 = createDocument("firstName", "fn3") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2014-04-17T16:02:48.440Z")) - .put("data", new byte[]{9, 4, 8}) - .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + - "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); - - NitriteCollection collection; - - db = TestUtil.createDb(fileName); - - collection = db.getCollection("test"); - - WriteResult result = collection.insert(doc1, doc2, doc3); - assertEquals(result.getAffectedCount(), 3); - - db.commit(); - db.close(); - } - - void readCollection() throws ParseException { - NitriteCollection collection; - - db = TestUtil.createDb(fileName); - - collection = db.getCollection("test"); - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").gt(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").gte(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lt(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lte(new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").lt(new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").gt(new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").gte(new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").lte(new Date()).and(where("firstName").eq("fn1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte(new Date()).or(where("firstName").eq("fn12"))); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1")) - .not()); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").eq((byte) 4)); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").lt(4)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("firstName").notIn("fn1", "fn2")); - assertEquals(cursor.size(), 1); - - collection.createIndex("birthDay", indexOptions(IndexType.Unique)); - cursor = collection.find().sort("birthDay", SortOrder.Descending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(TestUtil.isSorted(dateList, false)); - - cursor = collection.find(where("body").text("Lorem")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("body").text("quick")); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("body").text("nosql")); - assertEquals(cursor.size(), 0); - - db.close(); - } - - void deleteDb() throws IOException { - if (db != null && !db.isClosed()) { - db.close(); - } - - TestUtil.deleteFile(fileName); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/DbWriteCloseReadTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/DbWriteCloseReadTest.java deleted file mode 100644 index fc9a25094..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/DbWriteCloseReadTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb; - -import org.junit.Rule; -import org.junit.Test; - -import java.text.ParseException; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * @author Anindya Chatterjee. - */ -public class DbWriteCloseReadTest { - private final DbTestOperations operations = new DbTestOperations(); - private volatile boolean writeCompleted = false; - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testWriteCloseRead() throws Exception { - try { - operations.createDb(); - operations.writeCollection(); - operations.writeIndex(); - operations.insertInCollection(); - } catch (ParseException pe) { - // ignore - } finally { - writeCompleted = true; - } - - try { - assertTrue(writeCompleted); - operations.readCollection(); - } catch (Exception e) { - fail("collection read failed - " + e.getMessage()); - } finally { - operations.deleteDb(); - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/DocumentMetadataTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/DocumentMetadataTest.java deleted file mode 100644 index 3d1268415..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/DocumentMetadataTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.events.EventType; -import org.junit.Test; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee. - */ -public class DocumentMetadataTest extends BaseCollectionTest { - @Test - public void testTimeStamp() { - Document document = createDocument("test_key", "test_value"); - assertEquals(document.getRevision().intValue(), 0); - assertEquals(document.getLastModifiedSinceEpoch().longValue(), 0L); - - collection.insert(document); - document = collection.find().firstOrNull(); - - assertEquals(document.getRevision().intValue(), 1); - assertTrue(document.getLastModifiedSinceEpoch() > 0); - - long previous = document.getRevision(); - - DocumentCursor cursor = collection.find(where("test_key").eq("test_value")); - document = cursor.firstOrNull(); - document.put("another_key", "another_value"); - - collection.update(document); - cursor = collection.find(where("test_key").eq("test_value")); - document = cursor.firstOrNull(); - - assertTrue(document.getRevision() > previous); - - final long time = document.getRevision(); - final Document removed = document; - - collection.subscribe(changeInfo -> { - if (changeInfo.getEventType() == EventType.Remove) { - assertTrue(removed.getRevision() > time); - } - }); - - collection.remove(document); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/EntrySetTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/EntrySetTest.java new file mode 100644 index 000000000..6aedeba98 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/EntrySetTest.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.rocksdb; + +import org.dizitart.no2.rocksdb.formatter.KryoObjectFormatter; +import org.junit.Test; +import org.rocksdb.ColumnFamilyHandle; +import org.rocksdb.RocksDB; +import org.rocksdb.RocksIterator; + +import static org.mockito.Mockito.*; + +public class EntrySetTest { + @Test + public void testIterator() { + RocksDB rocksDB = mock(RocksDB.class); + when(rocksDB.newIterator((ColumnFamilyHandle) any())).thenReturn(mock(RocksIterator.class)); + KryoObjectFormatter objectFormatter = new KryoObjectFormatter(); + Class keyType = Object.class; + (new EntrySet<>(rocksDB, null, objectFormatter, keyType, Object.class, true)).iterator(); + verify(rocksDB).newIterator((ColumnFamilyHandle) any()); + } + + @Test + public void testIterator2() { + RocksDB rocksDB = mock(RocksDB.class); + when(rocksDB.newIterator((ColumnFamilyHandle) any())).thenReturn(mock(RocksIterator.class)); + KryoObjectFormatter objectFormatter = new KryoObjectFormatter(); + Class keyType = Object.class; + (new EntrySet<>(rocksDB, null, objectFormatter, keyType, Object.class, false)).iterator(); + verify(rocksDB).newIterator((ColumnFamilyHandle) any()); + } +} + diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/KeySetTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/KeySetTest.java new file mode 100644 index 000000000..af2613db3 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/KeySetTest.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.rocksdb; + +import org.dizitart.no2.rocksdb.formatter.KryoObjectFormatter; +import org.junit.Test; +import org.rocksdb.ColumnFamilyHandle; +import org.rocksdb.RocksDB; +import org.rocksdb.RocksIterator; + +import static org.mockito.Mockito.*; + +public class KeySetTest { + @Test + public void testIterator() { + RocksDB rocksDB = mock(RocksDB.class); + when(rocksDB.newIterator((ColumnFamilyHandle) any())).thenReturn(mock(RocksIterator.class)); + KryoObjectFormatter objectFormatter = new KryoObjectFormatter(); + (new KeySet<>(rocksDB, null, objectFormatter, Object.class)).iterator(); + verify(rocksDB).newIterator((ColumnFamilyHandle) any()); + } +} + diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/MultiThreadedTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/MultiThreadedTest.java deleted file mode 100644 index c9b53257d..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/MultiThreadedTest.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.concurrent.ThreadPoolManager; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.util.Date; -import java.util.Random; -import java.util.UUID; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - - -/** - * @author Anindya Chatterjee. - */ -public class MultiThreadedTest extends AbstractTest { - private NitriteCollection collection; - private final int threadCount = 20; - private final CountDownLatch latch = new CountDownLatch(threadCount); - private final int iterationCount = 100; - private final Random generator = new Random(); - private final AtomicInteger docCounter = new AtomicInteger(0); - private ExecutorService executor = ThreadPoolManager.getThreadPool(threadCount, "MultiThreadedTest"); - - @Rule - public Retry retry = new Retry(3); - - - @Test - public void testOperations() throws InterruptedException { - collection = db.getCollection("test"); - collection.remove(Filter.ALL); - collection.createIndex("unixTime", IndexOptions.indexOptions(IndexType.Unique)); - db.commit(); - - for (int i = 0; i < threadCount; i++) { - executor.submit(() -> { - for (int j = 0; j < iterationCount; j++) { - try { - Document document = generate(); - collection.insert(document); - - if (j == iterationCount / 2 - && !collection.hasIndex("text") - && !collection.hasIndex("date")) { - collection.createIndex("text", IndexOptions.indexOptions(IndexType.Fulltext)); - collection.createIndex("date", IndexOptions.indexOptions(IndexType.NonUnique)); - } - - long unixTime = (long) document.get("unixTime"); - DocumentCursor cursor = collection.find(where("unixTime").eq(unixTime)); - assertTrue(cursor.size() >= 0); - - if (collection.hasIndex("text") && !collection.isIndexing("text")) { - String textData = (String) document.get("text"); - cursor = collection.find(where("text").text(textData)); - assertTrue(cursor.size() >= 0); - } - - assertTrue(collection.hasIndex("unixTime")); - } catch (Throwable e) { - System.out.println("Exception at thread " + - Thread.currentThread().getName() + " with iteration " + j); - e.printStackTrace(); - } - } - latch.countDown(); - }); - } - - latch.await(); - - db.commit(); - - assertTrue(collection.hasIndex("text")); - assertTrue(collection.hasIndex("date")); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), docCounter.get()); - - cursor = collection.find(where("unixTime").gt(1L)); - assertEquals(cursor.size(), docCounter.get()); - - db.close(); - } - - @After - public void cleanUp() throws IOException { - super.cleanUp(); - - if (executor != null && !executor.isShutdown()) { - executor.shutdown(); - executor = null; - } - } - - private synchronized Document generate() { - Document document = createDocument("unixTime", System.nanoTime() + docCounter.incrementAndGet()); - byte[] blob = new byte[1024]; - generator.nextBytes(blob); - document.put("blob", blob); - document.put("text", UUID.randomUUID().toString().replaceAll("-", " ")); - document.put("date", new Date()); - return document; - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteBuilderNegativeTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteBuilderNegativeTest.java deleted file mode 100644 index 3af4e8a9c..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteBuilderNegativeTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; - -import static org.dizitart.no2.rocksdb.DbTestOperations.getRandomTempDbFile; - - -/** - * @author Anindya Chatterjee. - */ -public class NitriteBuilderNegativeTest { - private final String filePath = getRandomTempDbFile(); - private Nitrite db1, db2; - - @Rule - public Retry retry = new Retry(3); - - @Test(expected = NitriteIOException.class) - public void testOpenWithLock() { - db1 = TestUtil.createDb(filePath); - db2 = TestUtil.createDb(filePath); - } - - @Test(expected = NitriteIOException.class) - public void testInvalidDirectory() { - String filePath = "/ytgr/hfurh/frij.db"; - db1 = TestUtil.createDb(filePath); - } - - @After - public void cleanUp() throws IOException { - if (db1 != null && !db1.isClosed()) { - db1.close(); - } - - if (db2 != null && !db2.isClosed()) { - db2.close(); - } - TestUtil.deleteFile(filePath); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteBuilderTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteBuilderTest.java deleted file mode 100644 index 895048181..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteBuilderTest.java +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb; - -import org.apache.commons.io.FileUtils; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.NitriteConfig; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.SecurityException; -import org.dizitart.no2.index.Indexer; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.store.NitriteMap; -import org.dizitart.no2.store.StoreConfig; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.common.util.StringUtils.isNullOrEmpty; -import static org.dizitart.no2.module.NitriteModule.module; -import static org.dizitart.no2.rocksdb.DbTestOperations.getRandomTempDbFile; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class NitriteBuilderTest { - private String fakeFile; - private String filePath; - private Nitrite db; - private Nitrite fakeDb; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void startup() { - fakeFile = getRandomTempDbFile(); - filePath = getRandomTempDbFile(); - } - - @After - public void cleanup() throws IOException { - (new NitriteConfig()).fieldSeparator("."); - - if (db != null && !db.isClosed()) { - db.close(); - } - - if (Files.exists(Paths.get(filePath))) { - TestUtil.deleteFile(filePath); - } - - if (fakeDb != null && !fakeDb.isClosed()){ - fakeDb.close(); - } - - if (Files.exists(Paths.get(fakeFile))) { - TestUtil.deleteFile(fakeFile); - } - } - - @Test - public void testConfig() throws IOException { - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(filePath) - .build(); - - NitriteBuilder nitriteBuilder = Nitrite.builder(); - nitriteBuilder.loadModule(module(new CustomIndexer())); - nitriteBuilder.loadModule(storeModule); - - db = nitriteBuilder.openOrCreate(); - NitriteConfig config = nitriteBuilder.getNitriteConfig(); - RocksDBConfig storeConfig = (RocksDBConfig) db.getStore().getStoreConfig(); - - assertEquals(config.findIndexer("Custom").getClass(), CustomIndexer.class); - assertFalse(storeConfig.isReadOnly()); - assertFalse(storeConfig.isInMemory()); - assertFalse(isNullOrEmpty(storeConfig.filePath())); - - db.close(); - TestUtil.deleteFile(filePath); - } - - @Test - public void testConfigWithFile() throws IOException { - File file = new File(filePath); - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(file) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(); - StoreConfig storeConfig = db.getStore().getStoreConfig(); - - assertFalse(storeConfig.isInMemory()); - assertFalse(isNullOrEmpty(storeConfig.filePath())); - - NitriteCollection test = db.getCollection("test"); - assertNotNull(test); - - db.commit(); - db.close(); - - FileUtils.deleteDirectory(file.getAbsoluteFile()); - } - - @Test(expected = InvalidOperationException.class) - public void testConfigWithFileNull() { - File file = null; - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(file) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(); - StoreConfig storeConfig = db.getStore().getStoreConfig(); - - assertTrue(storeConfig.isInMemory()); - assertTrue(isNullOrEmpty(storeConfig.filePath())); - - NitriteCollection test = db.getCollection("test"); - assertNotNull(test); - - db.commit(); - db.close(); - } - - @Test - public void testPopulateRepositories() { - File file = new File(filePath); - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(file) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(); - - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("id1", "value")); - - ObjectRepository repository = db.getRepository(TestObject.class); - repository.insert(new TestObject("test", 1L)); - - ObjectRepository repository2 = db.getRepository(TestObject.class, "key"); - TestObject object = new TestObject(); - object.stringValue = "test2"; - object.longValue = 2L; - repository2.insert(object); - - ObjectRepository repository3 = db.getRepository(TestObject2.class, "key"); - TestObject2 object2 = new TestObject2(); - object2.stringValue = "test2"; - object2.longValue = 2L; - repository3.insert(object2); - - db.commit(); - db.close(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(); - assertTrue(db.hasCollection("test")); - assertTrue(db.hasRepository(TestObject.class)); - assertTrue(db.hasRepository(TestObject.class, "key")); - assertFalse(db.hasRepository(TestObject2.class)); - assertTrue(db.hasRepository(TestObject2.class, "key")); - } - - - @Test - public void testNitriteMapper() { - NitriteBuilder builder = Nitrite.builder(); - builder.loadModule(module(new CustomNitriteMapper())); - NitriteConfig config = builder.getNitriteConfig(); - assertNotNull(config.nitriteMapper()); - } - - @Test(expected = SecurityException.class) - public void testOpenOrCreateNullUserId() { - NitriteBuilder builder = Nitrite.builder(); - builder.openOrCreate(null, "abcd"); - } - - @Test(expected = SecurityException.class) - public void testOpenOrCreateNullPassword() { - NitriteBuilder builder = Nitrite.builder(); - builder.openOrCreate("abcd", null); - } - - - @Test(expected = NitriteIOException.class) - public void testDbInvalidDirectory() { - fakeFile = System.getProperty("java.io.tmpdir") + File.separator + "fake" + File.separator + "fake.db"; - db = TestUtil.createDb(fakeFile, "test", "test"); - assertNull(db); - } - - @Test - public void testFieldSeparator() { - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(filePath) - .build(); - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator("::") - .openOrCreate(); - - Document document = createDocument("firstName", "John") - .put("colorCodes", new Document[]{createDocument("color", "Red"), createDocument("color", "Green")}) - .put("address", createDocument("street", "ABCD Road")); - - String street = document.get("address::street", String.class); - assertEquals("ABCD Road", street); - - // use default separator, it should return null - street = document.get("address.street", String.class); - assertNull(street); - - assertEquals(document.get("colorCodes::1::color"), "Green"); - } - - private static class CustomIndexer implements Indexer { - - @Override - public String getIndexType() { - return "Custom"; - } - - @Override - public void writeIndex(NitriteMap collection, NitriteId nitriteId, String field, Object fieldValue) { - - } - - @Override - public void removeIndex(NitriteMap collection, NitriteId nitriteId, String field, Object fieldValue) { - - } - - @Override - public void updateIndex(NitriteMap collection, NitriteId nitriteId, String field, Object newValue, Object oldValue) { - - } - - @Override - public void dropIndex(NitriteMap collection, String field) { - - } - - @Override - public Indexer clone() throws CloneNotSupportedException { - return null; - } - - @Override - public void initialize(NitriteConfig nitriteConfig) { - - } - } - - public static class CustomNitriteMapper implements NitriteMapper { - - @Override - public Target convert(Source source, Class type) { - return null; - } - - @Override - public boolean isValueType(Class type) { - return false; - } - - @Override - public boolean isValue(Object object) { - return false; - } - - @Override - public void initialize(NitriteConfig nitriteConfig) { - - } - } - - @Index(value = "longValue") - private static class TestObject implements Mappable { - private String stringValue; - private Long longValue; - - public TestObject() { - } - - public TestObject(String stringValue, Long longValue) { - this.longValue = longValue; - this.stringValue = stringValue; - } - - @Override - public Document write(NitriteMapper mapper) { - return createDocument("stringValue", stringValue) - .put("longValue", longValue); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - if (document != null) { - this.stringValue = document.get("stringValue", String.class); - this.longValue = document.get("longValue", Long.class); - } - } - } - - @Index(value = "longValue") - private static class TestObject2 implements Mappable { - private String stringValue; - private Long longValue; - - public TestObject2() { - } - - public TestObject2(String stringValue, Long longValue) { - this.longValue = longValue; - this.stringValue = stringValue; - } - - @Override - public Document write(NitriteMapper mapper) { - return createDocument("stringValue", stringValue) - .put("longValue", longValue); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - if (document != null) { - this.stringValue = document.get("stringValue", String.class); - this.longValue = document.get("longValue", Long.class); - } - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteCorruptedTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteCorruptedTest.java deleted file mode 100644 index 4dcfdf1ca..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteCorruptedTest.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.concurrent.ThreadPoolManager; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.util.concurrent.ExecutorService; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.rocksdb.DbTestOperations.getRandomTempDbFile; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee - */ -public class NitriteCorruptedTest { - private Nitrite db; - private NitriteCollection collection; - private final String fileName = getRandomTempDbFile(); - private Thread thread; - private final ExecutorService dbPool = ThreadPoolManager.getThreadPool(Runtime.getRuntime().availableProcessors(), - "NitriteCorruptedTest"); - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - db = TestUtil.createDb(fileName); - - collection = db.getCollection("test"); - collection.remove(ALL); - - thread = new Thread(() -> { - for (int i = 0; i < 50000; i++) { - - // Interruption Guard - if (Thread.interrupted()) { - break; - } - - Document doc1 = createDocument(String.valueOf(System.currentTimeMillis()), "fn1") - .put("lastName", "ln1") - .put("data", new byte[]{1, 2, 3}) - .put("body", "a quick brown fox jump over the lazy dog"); - - // Separate user thread from Db write thread - dbPool.submit(() -> collection.insert(doc1)); - } - }); - } - - @After - public void tearDown() throws IOException { - if (collection.isOpen()) { - collection.remove(ALL); - collection.close(); - } - if (db != null && !db.isClosed()) { - db.close(); - } - TestUtil.deleteFile(fileName); - } - - @Test(timeout = 10000) - public void issue118() throws InterruptedException { - try { - thread.start(); - Thread.sleep(10); - thread.interrupt(); - Thread.sleep(500); - assertTrue(collection.isOpen()); - assertFalse(db.isClosed()); - } catch (InterruptedException e) { - if (db != null && !db.isClosed()) { - db.close(); - } - throw e; - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteStoreFactoryNegativeTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteStoreFactoryNegativeTest.java deleted file mode 100644 index 784cc8700..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteStoreFactoryNegativeTest.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.exceptions.NitriteException; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.rocksdb.DbTestOperations.getRandomTempDbFile; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class NitriteStoreFactoryNegativeTest { - private final String fileName = getRandomTempDbFile(); - - @Rule - public Retry retry = new Retry(3); - - @Test(expected = NitriteException.class) - public void testOpenSecuredWithoutCredential() throws IOException { - try(Nitrite db = TestUtil.createDb(fileName, "test-user", "test-password")) { - NitriteCollection dbCollection = db.getCollection("test"); - dbCollection.insert(createDocument("test", "test")); - db.commit(); - db.close(); - - - try(Nitrite db2 = TestUtil.createDb(fileName)){ - dbCollection = db2.getCollection("test"); - assertEquals(dbCollection.find().size(), 1); - } - } finally { - TestUtil.deleteFile(fileName); - } - } - - @Test(expected = NitriteException.class) - public void testOpenUnsecuredWithCredential() throws IOException { - try(Nitrite db = TestUtil.createDb(fileName)) { - NitriteCollection dbCollection = db.getCollection("test"); - dbCollection.insert(createDocument("test", "test")); - db.commit(); - db.close(); - - try(Nitrite db2 = TestUtil.createDb(fileName, "test-user", "test-password")) { - dbCollection = db2.getCollection("test"); - assertEquals(dbCollection.find().size(), 1); - } - } finally { - TestUtil.deleteFile(fileName); - } - } - - @Test(expected = NitriteException.class) - public void testWrongCredential() throws IOException { - try(Nitrite db = TestUtil.createDb(fileName, "test-user", "test-password")) { - NitriteCollection dbCollection = db.getCollection("test"); - dbCollection.insert(createDocument("test", "test")); - db.commit(); - db.close(); - - try(Nitrite db2 = TestUtil.createDb(fileName, "test-user", "test-password2")) { - dbCollection = db2.getCollection("test"); - assertEquals(dbCollection.find().size(), 1); - } - } finally { - TestUtil.deleteFile(fileName); - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteStoreFactoryTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteStoreFactoryTest.java deleted file mode 100644 index 539524ec2..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteStoreFactoryTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb; - -import org.apache.commons.io.FileUtils; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.exceptions.SecurityException; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.io.File; -import java.io.IOException; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.rocksdb.DbTestOperations.getRandomTempDbFile; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee. - */ -public class NitriteStoreFactoryTest { - private Nitrite db; - private final String fileName = getRandomTempDbFile(); - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testSecured() throws IOException { - db = TestUtil.createDb(fileName, "test-user", "test-password"); - NitriteCollection dbCollection = db.getCollection("test"); - dbCollection.insert(createDocument("test", "test")); - db.commit(); - db.close(); - - db = TestUtil.createDb(fileName, "test-user", "test-password"); - dbCollection = db.getCollection("test"); - assertEquals(dbCollection.find().size(), 1); - db.close(); - TestUtil.deleteFile(fileName); - } - - @Test - public void testUnsecured() throws IOException { - db = TestUtil.createDb(fileName); - NitriteCollection dbCollection = db.getCollection("test"); - dbCollection.insert(createDocument("test", "test")); - db.commit(); - db.close(); - - db = TestUtil.createDb(fileName); - dbCollection = db.getCollection("test"); - assertEquals(dbCollection.find().size(), 1); - db.close(); - TestUtil.deleteFile(fileName); - } - - @Test - public void testIssue116() throws IOException { - db = TestUtil.createDb(fileName, "test-user", "test-password"); - db.close(); - try { - db = TestUtil.createDb(fileName,"test-user2", "test-password2"); - } catch (SecurityException se) { - db = TestUtil.createDb(fileName,"test-user", "test-password"); - assertNotNull(db); - } finally { - db.close(); - TestUtil.deleteFile(fileName); - } - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - - FileUtils.deleteQuietly(new File(fileName)); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteStressTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteStressTest.java deleted file mode 100644 index 4b99fa812..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteStressTest.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Id; -import org.junit.Rule; -import org.junit.Test; -import uk.co.jemos.podam.api.PodamFactory; -import uk.co.jemos.podam.api.PodamFactoryImpl; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlSchemaType; -import java.util.ArrayList; -import java.util.List; - -import static org.junit.Assert.assertEquals; - - -/** - * @author Anindya Chatterjee - */ -public class NitriteStressTest extends AbstractTest { - private static final int TEST_SET_COUNT = 15000; - private final PodamFactory podamFactory = new PodamFactoryImpl(); - - @Rule - public Retry retry = new Retry(3); - - @Test - public void stressTest() { - ObjectRepository testRepository = db.getRepository(TestDto.class); - testRepository.createIndex("lastName", IndexOptions.indexOptions(IndexType.Fulltext)); - testRepository.createIndex("birthDate", IndexOptions.indexOptions(IndexType.NonUnique)); - - int counter = 0; - try { - for (TestDto testDto : createTestSet()) { - testRepository.insert(testDto); - counter++; - } - } catch (Throwable t) { - System.err.println("Crashed after " + counter + " records"); - throw t; - } - - int size = testRepository.find().toList().size(); - assertEquals(counter, size); - } - - private List createTestSet() { - List testData = new ArrayList<>(); - for (int i = 0; i < TEST_SET_COUNT; i++) { - TestDto testRecords = podamFactory.manufacturePojo(TestDto.class); - testData.add(testRecords); - } - return testData; - } - - @Data - public static class TestDto implements Mappable { - - @XmlElement( - name = "StudentNumber", - required = true - ) - @Id - protected String studentNumber; - - @XmlElement( - name = "LastName", - required = true - ) - protected String lastName; - - @XmlElement( - name = "Prefixes" - ) - protected String prefixes; - - @XmlElement( - name = "Initials", - required = true - ) - protected String initials; - - @XmlElement( - name = "FirstNames" - ) - protected String firstNames; - @XmlElement( - name = "Nickname" - ) - protected String nickName; - - @XmlElement( - name = "BirthDate", - required = true - ) - @XmlSchemaType( - name = "date" - ) - protected String birthDate; - - - public TestDto() { - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("studentNumber", studentNumber) - .put("lastName", lastName) - .put("prefixes", prefixes) - .put("initials", initials) - .put("firstNames", firstNames) - .put("nickName", nickName) - .put("birthDate", birthDate); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - studentNumber = document.get("studentNumber", String.class); - lastName = document.get("lastName", String.class); - prefixes = document.get("prefixes", String.class); - initials = document.get("initials", String.class); - firstNames = document.get("firstNames", String.class); - nickName = document.get("nickName", String.class); - birthDate = document.get("birthDate", String.class); - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteTest.java deleted file mode 100644 index 8388a1362..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/NitriteTest.java +++ /dev/null @@ -1,411 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.UpdateOptions; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.common.concurrent.ThreadPoolManager; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import uk.co.jemos.podam.api.PodamFactory; -import uk.co.jemos.podam.api.PodamFactoryImpl; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Locale; -import java.util.Random; -import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.common.Constants.INTERNAL_NAME_SEPARATOR; -import static org.dizitart.no2.common.Constants.META_MAP_NAME; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class NitriteTest extends AbstractTest { - - private NitriteCollection collection; - private SimpleDateFormat simpleDateFormat; - - @Before - public void setUp() throws ParseException { - db = TestUtil.createDb(fileName, "test-user", "test-password"); - - simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); - - Document doc1 = createDocument("firstName", "fn1") - .put("lastName", "ln1") - .put("birthDay", simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) - .put("data", new byte[]{1, 2, 3}) - .put("body", "a quick brown fox jump over the lazy dog"); - Document doc2 = createDocument("firstName", "fn2") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2010-06-12T16:02:48.440Z")) - .put("data", new byte[]{3, 4, 3}) - .put("body", "hello world from nitrite"); - Document doc3 = createDocument("firstName", "fn3") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2014-04-17T16:02:48.440Z")) - .put("data", new byte[]{9, 4, 8}) - .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + - "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); - - collection = db.getCollection("test"); - collection.remove(ALL); - - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.Unique)); - collection.insert(doc1, doc2, doc3); - } - - @After - public void tearDown() { - if (collection.isOpen()) { - collection.remove(ALL); - collection.close(); - } - } - - @Test - public void testListCollectionNames() { - Set collectionNames = db.listCollectionNames(); - assertEquals(collectionNames.size(), 1); - } - - @Test - public void testListRepositories() { - db.getRepository(getClass()); - Set repositories = db.listRepositories(); - assertEquals(repositories.size(), 1); - } - - @Test - public void testHasCollection() { - assertTrue(db.hasCollection("test")); - assertFalse(db.hasCollection("lucene" + INTERNAL_NAME_SEPARATOR + "test")); - } - - @Test - public void testHasRepository() { - db.getRepository(getClass()); - assertTrue(db.hasRepository(getClass())); - assertFalse(db.hasRepository(String.class)); - } - - - @Test - public void testReopen() throws ParseException { - assertNotNull(db); - NitriteCollection testCollection = db.getCollection("test"); - assertNotNull(testCollection); - long prevSize = testCollection.find().size(); - - db.close(); - - db = null; - - db = TestUtil.createDb(fileName, "test-user", "test-password"); - - assertNotNull(db); - testCollection = db.getCollection("test"); - assertNotNull(testCollection); - long sizeNow = testCollection.find().size(); - assertEquals(prevSize, sizeNow); - - db.close(); - db = null; - db = TestUtil.createDb(fileName, "test-user", "test-password"); - - testCollection = db.getCollection("test"); - testCollection.insert(createDocument("firstName", "fn12") - .put("lastName", "ln12") - .put("birthDay", simpleDateFormat.parse("2010-07-01T16:02:48.440Z")) - .put("data", new byte[]{10, 20, 30}) - .put("body", "a quick brown fox jump over the lazy dog")); - - db.close(); - db = null; - db = TestUtil.createDb(fileName, "test-user", "test-password"); - - testCollection = db.getCollection("test"); - assertNotNull(testCollection); - sizeNow = testCollection.find().size(); - assertEquals(prevSize + 1, sizeNow); - } - - @Test - public void testClose() { - NitriteCollection testCollection = db.getCollection("test"); - testCollection.insert(createDocument("a", "b")); - db.close(); - - assertFalse(testCollection.isOpen()); - } - - @Test - public void testGetCollection() { - NitriteCollection collection = db.getCollection("test-collection"); - assertNotNull(collection); - assertEquals(collection.getName(), "test-collection"); - } - - @Test - public void testGetRepository() { - ObjectRepository repository = db.getRepository(NitriteTest.class); - assertNotNull(repository); - assertEquals(repository.getType(), NitriteTest.class); - } - - @Test - public void testGetRepositoryWithKey() { - ObjectRepository repository = db.getRepository(NitriteTest.class, "key"); - assertNotNull(repository); - assertEquals(repository.getType(), NitriteTest.class); - assertFalse(db.hasRepository(NitriteTest.class)); - assertTrue(db.hasRepository(NitriteTest.class, "key")); - } - - @Test - public void testMultipleGetCollection() { - NitriteCollection collection = db.getCollection("test-collection"); - assertNotNull(collection); - assertEquals(collection.getName(), "test-collection"); - - NitriteCollection collection2 = db.getCollection("test-collection"); - assertNotNull(collection2); - assertEquals(collection2.getName(), "test-collection"); - } - - @Test - public void testMultipleGetRepository() { - ObjectRepository repository = db.getRepository(NitriteTest.class); - assertNotNull(repository); - assertEquals(repository.getType(), NitriteTest.class); - - ObjectRepository repository2 = db.getRepository(NitriteTest.class); - assertNotNull(repository2); - assertEquals(repository2.getType(), NitriteTest.class); - } - - @Test(expected = ValidationException.class) - public void testGetRepositoryInvalid() { - db.getRepository(null); - } - - @Test(expected = NitriteIOException.class) - public void testGetCollectionNullStore() { - db = Nitrite.builder().openOrCreate(); - db.close(); - db.getCollection("test"); - } - - @Test(expected = NitriteIOException.class) - public void testGetRepositoryNullStore() { - db = Nitrite.builder().openOrCreate(); - db.close(); - db.getRepository(NitriteTest.class); - } - - @Test(expected = NitriteIOException.class) - public void testGetKeyedRepositoryNullStore() { - db = Nitrite.builder().openOrCreate(); - db.close(); - db.getRepository(NitriteTest.class, "key"); - } - - @Test(expected = NitriteIOException.class) - public void testCommitNullStore() { - db = Nitrite.builder().openOrCreate(); - db.close(); - db.commit(); - } - - @Test(expected = ValidationException.class) - public void testGetCollectionInvalidName() { - db.getCollection(META_MAP_NAME); - } - - @Test - public void testIssue185() throws InterruptedException { - final ObjectRepository repository = db.getRepository(Receipt.class); - final Receipt receipt = new Receipt(); - receipt.clientRef = "111-11111"; - receipt.status = Receipt.Status.PREPARING; - CountDownLatch latch = new CountDownLatch(1); - - new Thread(() -> { - for (int i = 0; i < 1000; ++i) { - try { - repository.update(receipt, true); - try { - Thread.sleep(50); - } catch (InterruptedException ignored) { - } - repository.remove(receipt); - try { - Thread.sleep(50); - } catch (InterruptedException ignored) { - } - } catch (Throwable t) { - t.printStackTrace(); - } - } - latch.countDown(); - }).start(); - - for (int i = 0; i < 1000; ++i) { - repository.find(where("status").eq(Receipt.Status.COMPLETED).not()) - .sort("createdTimestamp", SortOrder.Descending).toList(); - try { - Thread.sleep(50); - } catch (InterruptedException ignored) { - } - } - latch.await(); - } - - @Test - public void testIssue193() throws InterruptedException { - final ObjectRepository repository = db.getRepository(Receipt.class); - final PodamFactory factory = new PodamFactoryImpl(); - final String[] refs = new String[]{"1", "2", "3", "4", "5"}; - final Random random = new Random(); - ExecutorService pool = ThreadPoolManager.workerPool(); - - final CountDownLatch latch = new CountDownLatch(10000); - for (int i = 0; i < 10000; i++) { - pool.submit(() -> { - int refIndex = random.nextInt(5); - Receipt receipt = factory.manufacturePojoWithFullData(Receipt.class); - receipt.setClientRef(refs[refIndex]); - repository.update(receipt, true); - latch.countDown(); - }); - } - - latch.await(); - assertTrue(repository.find().size() <= 5); - pool.shutdown(); - } - - @Test - public void testIssue212() { - NitriteCollection collection = db.getCollection("testIssue212"); - Document doc1 = createDocument("key", "key").put("second_key", "second_key").put("third_key", "third_key"); - Document doc2 = createDocument("key", "key").put("second_key", "second_key").put("fourth_key", "fourth_key"); - Document doc = createDocument("fifth_key", "fifth_key"); - - if (!collection.hasIndex("key")) { - collection.createIndex("key", IndexOptions.indexOptions(IndexType.NonUnique)); - } - if (!collection.hasIndex("second_key")) { - collection.createIndex("second_key", IndexOptions.indexOptions(IndexType.NonUnique)); - } - - collection.insert(doc1, doc2); - collection.update(where("key").eq("key").and(where("second_key").eq("second_key")), - doc, UpdateOptions.updateOptions(true)); - - for (Document document : collection.find()) { - System.out.println(document); - } - } - - @Data - @AllArgsConstructor - @NoArgsConstructor - public static class CompatChild implements Mappable { - private Long childId; - private String lastName; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("childId", childId) - .put("lastName", lastName); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - childId = document.get("childId", Long.class); - lastName = document.get("lastName", String.class); - } - } - - @Data - @NoArgsConstructor - @AllArgsConstructor - @Indices({ - @Index(value = "synced", type = IndexType.NonUnique) - }) - public static class Receipt implements Mappable { - private Status status; - @Id - private String clientRef; - private Boolean synced; - private Long createdTimestamp = System.currentTimeMillis(); - - @Override - public Document write(NitriteMapper mapper) { - return createDocument("status", status) - .put("clientRef", clientRef) - .put("synced", synced) - .put("createdTimestamp", createdTimestamp); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - if (document != null) { - Object status = document.get("status"); - if (status instanceof Status) { - this.status = (Status) status; - } else { - this.status = Status.valueOf(status.toString()); - } - this.clientRef = document.get("clientRef", String.class); - this.synced = document.get("synced", Boolean.class); - this.createdTimestamp = document.get("createdTimestamp", Long.class); - } - } - public enum Status { - COMPLETED, - PREPARING, - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/Retry.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/Retry.java deleted file mode 100644 index 678729f08..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/Retry.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.dizitart.no2.rocksdb; - -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; - -/** - * @author Anindya Chatterjee - */ -public class Retry implements TestRule { - private final int retryCount; - - public Retry(int retryCount) { - this.retryCount = retryCount; - } - - public Statement apply(Statement base, Description description) { - return statement(base, description); - } - - private Statement statement(final Statement base, final Description description) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - Throwable caughtThrowable = null; - - // implement retry logic here - for (int i = 0; i < retryCount; i++) { - try { - base.evaluate(); - return; - } catch (Throwable t) { - caughtThrowable = t; - System.err.println(description.getDisplayName() + ": run " + (i + 1) + " failed"); - } - } - System.err.println(description.getDisplayName() + ": giving up after " + retryCount + " failures"); - throw caughtThrowable; - } - }; - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBConfigTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBConfigTest.java index 3d596672c..48a8c1312 100644 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBConfigTest.java +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBConfigTest.java @@ -1,9 +1,27 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.rocksdb; +import org.junit.Test; + import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; - -import org.junit.Test; +import static org.junit.Assert.assertTrue; public class RocksDBConfigTest { @Test @@ -12,5 +30,17 @@ public void testConstructor() { assertFalse(actualRocksDBConfig.isInMemory()); assertNull(actualRocksDBConfig.options()); } + + @Test + public void testConstructor2() { + assertFalse((new RocksDBConfig()).isInMemory()); + } + + @Test + public void testConstructor3() { + RocksDBConfig actualRocksDBConfig = new RocksDBConfig(); + assertTrue(actualRocksDBConfig.objectFormatter() instanceof org.dizitart.no2.rocksdb.formatter.KryoObjectFormatter); + assertTrue(actualRocksDBConfig.eventListeners().isEmpty()); + } } diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBMapTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBMapTest.java new file mode 100644 index 000000000..84f74a19a --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBMapTest.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.rocksdb; + +import org.junit.Test; + +import static org.mockito.Mockito.*; + +@SuppressWarnings("unchecked") +public class RocksDBMapTest { + @Test + public void testPutIfAbsent() { + RocksDBMap rocksDBMap = (RocksDBMap) mock(RocksDBMap.class); + when(rocksDBMap.putIfAbsent(any(), any())).thenReturn("42"); + rocksDBMap.putIfAbsent("42", "42"); + verify(rocksDBMap).putIfAbsent(any(), any()); + } +} + diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBModuleBuilderTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBModuleBuilderTest.java index ccd9edb25..bd6c87e4a 100644 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBModuleBuilderTest.java +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBModuleBuilderTest.java @@ -1,13 +1,64 @@ -package org.dizitart.no2.rocksdb; +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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. + * + */ -import static org.junit.Assert.assertNull; +package org.dizitart.no2.rocksdb; import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + public class RocksDBModuleBuilderTest { @Test public void testConstructor() { assertNull((new RocksDBModuleBuilder()).options()); } + + @Test + public void testConstructor2() { + RocksDBModuleBuilder actualRocksDBModuleBuilder = new RocksDBModuleBuilder(); + RocksDBModuleBuilder actualFilePathResult = actualRocksDBModuleBuilder.filePath("Path"); + assertNull(actualRocksDBModuleBuilder.columnFamilyOptions()); + assertNull(actualRocksDBModuleBuilder.options()); + assertNull(actualRocksDBModuleBuilder.objectFormatter()); + assertEquals("Path", actualRocksDBModuleBuilder.filePath()); + assertTrue(actualRocksDBModuleBuilder.eventListeners().isEmpty()); + assertNull(actualRocksDBModuleBuilder.dbOptions()); + RocksDBConfig dbConfigResult = actualRocksDBModuleBuilder.dbConfig(); + assertNull(dbConfigResult.columnFamilyOptions()); + assertNull(dbConfigResult.options()); + assertTrue(dbConfigResult.objectFormatter() instanceof org.dizitart.no2.rocksdb.formatter.KryoObjectFormatter); + assertFalse(dbConfigResult.isInMemory()); + assertNull(dbConfigResult.filePath()); + assertTrue(dbConfigResult.eventListeners().isEmpty()); + assertNull(dbConfigResult.dbOptions()); + assertSame(actualRocksDBModuleBuilder, actualFilePathResult); + } + + @Test + public void testConstructor3() { + RocksDBModuleBuilder actualRocksDBModuleBuilder = new RocksDBModuleBuilder(); + assertTrue(actualRocksDBModuleBuilder.eventListeners().isEmpty()); + RocksDBConfig dbConfigResult = actualRocksDBModuleBuilder.dbConfig(); + assertTrue(dbConfigResult.objectFormatter() instanceof org.dizitart.no2.rocksdb.formatter.KryoObjectFormatter); + assertTrue(dbConfigResult.eventListeners().isEmpty()); + } } diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBModuleTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBModuleTest.java index 814d28e94..d5930c9a1 100644 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBModuleTest.java +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBModuleTest.java @@ -1,13 +1,39 @@ -package org.dizitart.no2.rocksdb; +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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. + * + */ -import static org.junit.Assert.assertTrue; +package org.dizitart.no2.rocksdb; import org.junit.Test; +import static org.junit.Assert.assertTrue; + public class RocksDBModuleTest { @Test public void testConstructor() { assertTrue((new RocksDBModule("path")).getStore() instanceof RocksDBStore); } + + @Test + public void testWithConfig() { + RocksDBModuleBuilder actualWithConfigResult = RocksDBModule.withConfig(); + assertTrue(actualWithConfigResult.eventListeners().isEmpty()); + RocksDBConfig dbConfigResult = actualWithConfigResult.dbConfig(); + assertTrue(dbConfigResult.objectFormatter() instanceof org.dizitart.no2.rocksdb.formatter.KryoObjectFormatter); + assertTrue(dbConfigResult.eventListeners().isEmpty()); + } } diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBReferenceTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBReferenceTest.java index 82a5531de..4f9fd24aa 100644 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBReferenceTest.java +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBReferenceTest.java @@ -1,14 +1,38 @@ -package org.dizitart.no2.rocksdb; +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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. + * + */ -import static org.junit.Assert.assertEquals; +package org.dizitart.no2.rocksdb; import org.junit.Test; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + public class RocksDBReferenceTest { + @Test public void testConstructor() { - assertEquals("RocksDBReference(options=null, dbOptions=null, columnFamilyOptions=null, rocksDB=null, columnFamilyD" - + "escriptors=[], columnFamilyHandleRegistry={}, dbComparators=[])", (new RocksDBReference()).toString()); + RocksDBReference actualRocksDBReference = new RocksDBReference(); + assertTrue(actualRocksDBReference.getColumnFamilyDescriptors().isEmpty()); + assertNull(actualRocksDBReference.getRocksDB()); + assertNull(actualRocksDBReference.getOptions()); + assertNull(actualRocksDBReference.getDbOptions()); + assertNull(actualRocksDBReference.getColumnFamilyOptions()); + assertTrue(actualRocksDBReference.getColumnFamilyHandleRegistry().isEmpty()); } } diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBStoreTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBStoreTest.java index 117cc1474..d34087441 100644 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBStoreTest.java +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBStoreTest.java @@ -1,13 +1,61 @@ -package org.dizitart.no2.rocksdb; +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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. + * + */ -import static org.junit.Assert.assertTrue; +package org.dizitart.no2.rocksdb; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.dizitart.no2.exceptions.NitriteException; import org.junit.Test; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + public class RocksDBStoreTest { @Test public void testConstructor() { assertTrue((new RocksDBStore()).isClosed()); + assertTrue((new RocksDBStore()).isClosed()); + } + + @Test + public void testConstructor2() { + RocksDBStore actualRocksDBStore = new RocksDBStore(); + assertFalse(actualRocksDBStore.hasUnsavedChanges()); + assertFalse(actualRocksDBStore.isReadOnly()); + } + + @Test(expected = NitriteException.class) + public void testOpenMap() { + RocksDBConfig rocksDBConfig = mock(RocksDBConfig.class); + when(rocksDBConfig.objectFormatter()).thenThrow(new NitriteException("An error occurred")); + + RocksDBStore rocksDBStore = new RocksDBStore(); + rocksDBStore.setStoreConfig(rocksDBConfig); + Class keyType = Object.class; + rocksDBStore.openMap("Map Name", keyType, Object.class); + verify(rocksDBConfig).objectFormatter(); + } + + @Test + public void testOpenRTree() { + RocksDBStore rocksDBStore = new RocksDBStore(); + Class keyType = Object.class; + assertThrows(InvalidOperationException.class, + () -> rocksDBStore.openRTree("R Tree Name", keyType, Object.class)); } } diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBStoreUtilsTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBStoreUtilsTest.java new file mode 100644 index 000000000..43a478f04 --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBStoreUtilsTest.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.rocksdb; + +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.dizitart.no2.store.events.StoreEventListener; +import org.junit.Test; + +import static org.junit.Assert.assertThrows; +import static org.mockito.Mockito.mock; + +public class RocksDBStoreUtilsTest { + @Test + public void testOpenOrCreate() { + assertThrows(InvalidOperationException.class, () -> RocksDBStoreUtils.openOrCreate(new RocksDBConfig())); + } + + @Test + public void testOpenOrCreate2() { + RocksDBConfig rocksDBConfig = new RocksDBConfig(); + rocksDBConfig.addStoreEventListener(mock(StoreEventListener.class)); + assertThrows(InvalidOperationException.class, () -> RocksDBStoreUtils.openOrCreate(rocksDBConfig)); + } +} + diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBTest.java index 881f67602..175561fd7 100644 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBTest.java +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/RocksDBTest.java @@ -1,17 +1,18 @@ /* - * Copyright (c) 2019-2020. Nitrite author or authors. + * Copyright (c) 2017-2021 Nitrite author or authors. * * Licensed 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 + * 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.dizitart.no2.rocksdb; @@ -21,7 +22,12 @@ import com.esotericsoftware.kryo.io.Input; import com.github.javafaker.Faker; import lombok.Data; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.integration.Retry; import org.dizitart.no2.store.NitriteMap; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.rocksdb.*; @@ -29,14 +35,42 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; +import java.text.ParseException; import java.util.*; +import static org.dizitart.no2.integration.TestUtil.deleteDb; +import static org.dizitart.no2.integration.TestUtil.getRandomTempDbFile; import static org.junit.Assert.assertEquals; /** * @author Anindya Chatterjee */ -public class RocksDBTest extends AbstractTest { +public class RocksDBTest { + private final String fileName = getRandomTempDbFile(); + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() throws ParseException { + RocksDBModule storeModule = RocksDBModule.withConfig() + .filePath(fileName) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .fieldSeparator(".") + .openOrCreate(); + } + + @After + public void cleanUp() throws IOException { + if (db != null && !db.isClosed()) { + db.close(); + } + deleteDb(fileName); + } @Test public void testRocksDBMap() { diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/SerializabilityTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/SerializabilityTest.java deleted file mode 100644 index 3783e957d..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/SerializabilityTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb; - -import lombok.Data; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.exceptions.ValidationException; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.File; -import java.io.IOException; -import java.io.Serializable; - -import static org.dizitart.no2.rocksdb.DbTestOperations.getRandomTempDbFile; - -/** - * @author Anindya Chatterjee - */ -public class SerializabilityTest { - private Nitrite db; - private NitriteCollection collection; - private File dbFile; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - dbFile = new File(getRandomTempDbFile()); - db = TestUtil.createDb(dbFile.getPath()); - collection = db.getCollection("test"); - } - - @After - public void tearDown() throws IOException { - db.close(); - if (dbFile.exists()) { - TestUtil.deleteFile(dbFile.getPath()); - } - } - - @Test(expected = ValidationException.class) - public void testSerializabilityValidation() { - for (int i = 0; i < 5; i++) { - Document doc = Document.createDocument(); - doc.put("key", i); - doc.put("data", new NotSerializableClass(Integer.toString(i))); - collection.insert(doc); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("Write " + i + " completed"); - } - } - - @Test - public void testSerializablity() { - for (int i = 0; i < 5; i++) { - Document doc = Document.createDocument(); - doc.put("key", i); - doc.put("data", new SerializableClass(Integer.toString(i))); - collection.insert(doc); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("Write " + i + " completed"); - } - } - - @Data - public static class NotSerializableClass { - private String myId; - - public NotSerializableClass(String myId) { - this.myId = myId; - } - } - - @Data - public static class SerializableClass implements Serializable { - private String myId; - - public SerializableClass(String myId) { - this.myId = myId; - } - } -} - - diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/StressTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/StressTest.java deleted file mode 100644 index cea8c05be..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/StressTest.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import uk.co.jemos.podam.api.PodamFactory; -import uk.co.jemos.podam.api.PodamFactoryImpl; - -import java.io.IOException; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import java.util.concurrent.atomic.AtomicLong; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee - */ -public class StressTest extends AbstractTest { - private NitriteCollection collection; - - @Before - public void before() { - collection = db.getCollection("test"); - } - - @Test - public void testIssue41() { - collection.createIndex("number", IndexOptions.indexOptions(IndexType.NonUnique)); - collection.createIndex("name", IndexOptions.indexOptions(IndexType.NonUnique)); - collection.createIndex("counter", IndexOptions.indexOptions(IndexType.Unique)); - - Random random = new Random(); - AtomicLong counter = new AtomicLong(System.currentTimeMillis()); - PodamFactory factory = new PodamFactoryImpl(); - - long start = System.currentTimeMillis(); - for (int i = 0; i < 100000; i++) { - Document doc = Document.createDocument(); - doc.put("number", random.nextDouble()); - doc.put("name", factory.manufacturePojo(String.class)); - doc.put("counter", counter.getAndIncrement()); - collection.insert(doc); - if (i % 10000 == 0) { - System.out.println(i + " entries written"); - } - } - System.out.println("Records inserted in " + ((System.currentTimeMillis() - start) / (1000 * 60)) + " minutes"); - - if (db.hasUnsavedChanges()) { - db.commit(); - } - - start = System.currentTimeMillis(); - DocumentCursor cursor = collection.find(); - System.out.println("Size ->" + cursor.size()); - System.out.println("Records size calculated in " + ((System.currentTimeMillis() - start) / (1000)) + " seconds"); - - int i = 0; - start = System.currentTimeMillis(); - for (Document element : cursor) { - assertNotNull(element); - i++; - if (i % 10000 == 0) { - System.out.println(i + " entries processed"); - } - } - System.out.println("Iteration completed in " + ((System.currentTimeMillis() - start) / (1000)) + " seconds"); - } - - @Test - public void testRepoPerformanceWithIndex() { - // warm-up - List items = getItems(PerfTestIndexed.class); - ObjectRepository repo = db.getRepository(PerfTestIndexed.class); - for (PerfTestIndexed item : items) { - assertNotNull(item); - repo.insert(item); - } - repo.remove(Filter.ALL); - repo.drop(); - - // actual calculation - repo = db.getRepository(PerfTestIndexed.class); - long start = System.currentTimeMillis(); - for (PerfTestIndexed item : items) { - repo.insert(item); - } - long diff = System.currentTimeMillis() - start; - System.out.println("Time take to insert 10000 indexed items - " + diff + "ms"); - - start = System.currentTimeMillis(); - repo.remove(Filter.ALL); - diff = System.currentTimeMillis() - start; - System.out.println("Time take to remove 10000 indexed items - " + diff + "ms"); - } - - @Test - public void testRepoPerformanceWithoutIndex() { - // warm-up - List items = getItems(PerfTest.class); - ObjectRepository repo = db.getRepository(PerfTest.class); - for (PerfTest item : items) { - assertNotNull(item); - repo.insert(item); - } - repo.remove(Filter.ALL); - repo.drop(); - - // actual calculation - repo = db.getRepository(PerfTest.class); - long start = System.currentTimeMillis(); - for (PerfTest item : items) { - repo.insert(item); - } - long diff = System.currentTimeMillis() - start; - System.out.println("Time take to insert 10000 non-indexed items - " + diff + "ms"); - - start = System.currentTimeMillis(); - repo.remove(Filter.ALL); - diff = System.currentTimeMillis() - start; - System.out.println("Time take to remove 10000 non-indexed items - " + diff + "ms"); - } - - private List getItems(Class type) { - PodamFactory generator = new PodamFactoryImpl(); - List items = new ArrayList<>(); - for (int i = 0; i < 10000; i++) { - items.add(generator.manufacturePojoWithFullData(type)); - } - assertEquals(items.size(), 10000); - return items; - } - - @Data - public static class PerfTest implements Mappable { - private String firstName; - private String lastName; - private Integer age; - private String text; - - @Override - public Document write(NitriteMapper mapper) { - Document document = Document.createDocument(); - document.put("firstName", firstName); - document.put("lastName", lastName); - document.put("age", age); - document.put("text", text); - return document; - } - - @Override - public void read(NitriteMapper mapper, Document document) { - this.firstName = (String) document.get("firstName"); - this.lastName = (String) document.get("lastName"); - this.age = (Integer) document.get("age"); - this.text = (String) document.get("text"); - } - } - - @Indices({ - @Index(value = "firstName", type = IndexType.NonUnique), - @Index(value = "age", type = IndexType.NonUnique), - @Index(value = "text", type = IndexType.Fulltext), - }) - private static class PerfTestIndexed extends PerfTest { - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/TestUtil.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/TestUtil.java deleted file mode 100644 index f7b7833d4..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/TestUtil.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2019-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb; - -import com.fasterxml.jackson.databind.JsonNode; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.io.FileUtils; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; - -import java.io.File; -import java.io.IOException; -import java.util.*; - -/** - * @author Anindya Chatterjee - */ -@Slf4j -public class TestUtil { - - public static void deleteFile(String fileName) throws IOException { - File file = new File(fileName); - FileUtils.deleteDirectory(file); - } - - public static > boolean isSorted(Iterable iterable, boolean ascending) { - Iterator iterator = iterable.iterator(); - if (!iterator.hasNext()) { - return true; - } - T t = iterator.next(); - while (iterator.hasNext()) { - T t2 = iterator.next(); - if (ascending) { - if (t.compareTo(t2) > 0) { - return false; - } - } else { - if (t.compareTo(t2) < 0) { - return false; - } - } - t = t2; - } - return true; - } - - public static Nitrite createDb() { - RocksDBModule storeModule = RocksDBModule.withConfig() - .build(); - - return Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(); - } - - public static Nitrite createDb(String user, String password) { - RocksDBModule storeModule = RocksDBModule.withConfig() - .build(); - - return Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(user, password); - } - - public static Nitrite createDb(String filePath) { - return Nitrite.builder() - .loadModule(new RocksDBModule(filePath)) - .fieldSeparator(".") - .openOrCreate(); - } - - public static Nitrite createDb(String filePath, String user, String password) { - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(filePath) - .build(); - - return Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(user, password); - } - - private static Document loadDocument(JsonNode node) { - Map objectMap = new LinkedHashMap<>(); - Iterator> fields = node.fields(); - while (fields.hasNext()) { - Map.Entry entry = fields.next(); - String name = entry.getKey(); - JsonNode value = entry.getValue(); - Object object = loadObject(value); - objectMap.put(name, object); - } - - return Document.createDocument(objectMap); - } - - private static Object loadObject(JsonNode node) { - if (node == null) - return null; - try { - switch (node.getNodeType()) { - case ARRAY: - return loadArray(node); - case BINARY: - return node.binaryValue(); - case BOOLEAN: - return node.booleanValue(); - case MISSING: - case NULL: - return null; - case NUMBER: - return node.numberValue(); - case OBJECT: - case POJO: - return loadDocument(node); - case STRING: - return node.textValue(); - } - } catch (IOException e) { - return null; - } - return null; - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - private static List loadArray(JsonNode array) { - if (array.isArray()) { - List list = new ArrayList(); - Iterator iterator = array.elements(); - while (iterator.hasNext()) { - Object element = iterator.next(); - if (element instanceof JsonNode) { - list.add(loadObject((JsonNode) element)); - } else { - list.add(element); - } - } - return list; - } - return null; - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/ValueSetTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/ValueSetTest.java new file mode 100644 index 000000000..da392e50c --- /dev/null +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/ValueSetTest.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.rocksdb; + +import org.dizitart.no2.rocksdb.formatter.KryoObjectFormatter; +import org.junit.Test; +import org.rocksdb.ColumnFamilyHandle; +import org.rocksdb.RocksDB; +import org.rocksdb.RocksIterator; + +import static org.mockito.Mockito.*; + +public class ValueSetTest { + @Test + public void testIterator() { + RocksDB rocksDB = mock(RocksDB.class); + when(rocksDB.newIterator((ColumnFamilyHandle) any())).thenReturn(mock(RocksIterator.class)); + KryoObjectFormatter objectFormatter = new KryoObjectFormatter(); + (new ValueSet<>(rocksDB, null, objectFormatter, Object.class)).iterator(); + verify(rocksDB).newIterator((ColumnFamilyHandle) any()); + } +} + diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionDeleteNegativeTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionDeleteNegativeTest.java deleted file mode 100644 index 546d6cc0d..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionDeleteNegativeTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.collection; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.rocksdb.BaseCollectionTest; -import org.junit.Test; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionDeleteNegativeTest extends BaseCollectionTest { - @Test(expected = NitriteIOException.class) - public void testDrop() { - collection.drop(); - insert(); - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - } - - @Test(expected = FilterException.class) - public void testDeleteWithInvalidFilter() { - insert(); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - - WriteResult writeResult = collection.remove(where("lastName").gt(null)); - assertEquals(writeResult.getAffectedCount(), 0); - } - - @Test(expected = ValidationException.class) - public void testDeleteNullDocument() { - insert(); - - collection.remove((Document) null); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionDeleteTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionDeleteTest.java deleted file mode 100644 index d157dc682..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionDeleteTest.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.collection; - -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.rocksdb.BaseCollectionTest; -import org.junit.Test; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -public class CollectionDeleteTest extends BaseCollectionTest { - - @Test - public void testDelete() { - insert(); - - WriteResult writeResult = collection.remove(where("lastName").notEq(null)); - assertEquals(writeResult.getAffectedCount(), 3); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 0); - } - - @Test - public void testDeleteWithOptions() { - insert(); - - WriteResult writeResult = collection.remove(where("lastName").notEq(null), true); - assertEquals(writeResult.getAffectedCount(), 1); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 2); - } - - @Test - public void testDeleteWithNonMatchingFilter() { - insert(); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - - WriteResult writeResult = collection.remove(where("lastName").eq("a")); - assertEquals(writeResult.getAffectedCount(), 0); - } - - @Test - public void testDeleteInEmptyCollection() { - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 0); - - WriteResult writeResult = collection.remove(where("lastName").notEq(null)); - assertEquals(writeResult.getAffectedCount(), 0); - } - - @Test - public void testClear() { - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.Unique)); - insert(); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - assertTrue(collection.hasIndex("firstName")); - - boolean uniqueError = false; - try { - collection.insert(doc1); - } catch (Exception e) { - uniqueError = true; - } finally { - assertTrue(uniqueError); - } - - collection.remove(Filter.ALL); - - cursor = collection.find(); - assertEquals(cursor.size(), 0); - assertTrue(collection.hasIndex("firstName")); - - collection.insert(doc1); - cursor = collection.find(); - assertEquals(cursor.size(), 1); - assertTrue(collection.hasIndex("firstName")); - } - - @Test - public void testRemoveAll() { - insert(); - WriteResult writeResult = collection.remove((Filter) null); - assertEquals(writeResult.getAffectedCount(), 3); - } - - @Test - public void testRemoveDocument() { - insert(); - - WriteResult writeResult = collection.remove(where("firstName").eq("fn1")); - assertEquals(writeResult.getAffectedCount(), 1); - assertEquals(collection.size(), 2); - - writeResult = collection.remove(where("firstName").eq("fn2")); - assertEquals(writeResult.getAffectedCount(), 1); - assertEquals(collection.size(), 1); - - assertEquals(collection.find(where("firstName").eq("fn1")).size(), 0); - assertEquals(collection.find(where("firstName").eq("fn2")).size(), 0); - assertEquals(collection.find(where("firstName").eq("fn3")).size(), 1); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionFactoryTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionFactoryTest.java deleted file mode 100644 index e8806de40..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionFactoryTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.collection; - -import org.dizitart.no2.NitriteConfig; -import org.dizitart.no2.collection.CollectionFactory; -import org.dizitart.no2.common.concurrent.LockService; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.rocksdb.Retry; -import org.junit.Rule; -import org.junit.Test; - -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee - */ -public class CollectionFactoryTest { - - @Rule - public Retry retry = new Retry(3); - - @Test(expected = ValidationException.class) - public void testGetCollectionMapStoreNull() { - CollectionFactory factory = new CollectionFactory(new LockService()); - assertNotNull(factory); - - NitriteConfig config = new NitriteConfig(); - factory.getCollection(null, config, true); - } - - @Test(expected = ValidationException.class) - public void testGetCollectionContextNull() { - CollectionFactory factory = new CollectionFactory(new LockService()); - factory.getCollection("test", null, false); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionFindByIndexNegativeTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionFindByIndexNegativeTest.java deleted file mode 100644 index 174c8a6a6..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionFindByIndexNegativeTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.collection; - -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.rocksdb.BaseCollectionTest; -import org.junit.Test; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionFindByIndexNegativeTest extends BaseCollectionTest { - @Test(expected = FilterException.class) - public void testFindTextWithWildCardMultipleWord() { - insert(); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - - DocumentCursor cursor = collection.find(where("body").text("*ipsum dolor*")); - assertEquals(cursor.size(), 1); - } - - @Test(expected = FilterException.class) - public void testFindTextWithOnlyWildCard() { - insert(); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - - DocumentCursor cursor = collection.find(where("body").text("*")); - assertEquals(cursor.size(), 1); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionFindByIndexTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionFindByIndexTest.java deleted file mode 100644 index b4f659e12..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionFindByIndexTest.java +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.collection; - -import com.github.javafaker.Faker; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.rocksdb.BaseCollectionTest; -import org.junit.Test; - -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.rocksdb.TestUtil.isSorted; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionFindByIndexTest extends BaseCollectionTest { - - @Test - public void testFindByUniqueIndex() throws ParseException { - insert(); - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.Unique)); - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("firstName").eq("fn10")); - assertEquals(cursor.size(), 0); - - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.Unique)); - cursor = collection.find(where("birthDay").gt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").gte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lte( - new Date())); - - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").lt( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").gt( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").gte( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .and(where("firstName").eq("fn1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12"))); - assertEquals(cursor.size(), 3); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1")).not()); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").eq((byte) 4)); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").lt(4)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("firstName").notIn("fn1", "fn2")); - assertEquals(cursor.size(), 1); - } - - @Test - public void testFindByNonUniqueIndex() throws ParseException { - insert(); - collection.createIndex("lastName", IndexOptions.indexOptions(IndexType.NonUnique)); - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.NonUnique)); - - DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("lastName").eq("ln20")); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").gt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").gte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lte( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").lt( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").gt( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").gte( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .and(where("firstName").eq("fn1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12"))); - assertEquals(cursor.size(), 3); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1")).not()); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").eq((byte) 4)); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").lt(4)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("firstName").notIn("fn1", "fn2")); - assertEquals(cursor.size(), 1); - } - - @Test - public void testFindByFullTextIndexAfterInsert() { - insert(); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("body")); - - DocumentCursor cursor = collection.find(where("body").text("Lorem")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("body").text("nosql")); - assertEquals(cursor.size(), 0); - - collection.dropIndex("body"); - boolean filterException = false; - try { - collection.find(where("body").text("Lorem")).toList(); - } catch (FilterException fe) { - filterException = true; - } finally { - assertTrue(filterException); - } - } - - @Test - public void testFindByFullTextIndexBeforeInsert() { - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("body")); - insert(); - - DocumentCursor cursor = collection.find(where("body").text("Lorem")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("body").text("quick brown")); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("body").text("nosql")); - assertEquals(cursor.size(), 0); - - collection.dropIndex("body"); - boolean filterException = false; - try { - collection.find(where("body").text("Lorem")).toList(); - } catch (FilterException fe) { - filterException = true; - } finally { - assertTrue(filterException); - } - } - - @Test - public void testFindByIndexSortAscending() { - insert(); - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.Unique)); - - DocumentCursor cursor = collection.find().sort("birthDay", SortOrder.Ascending); - assertEquals(cursor.size(), 3); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, true)); - } - - @Test - public void testFindByIndexSortDescending() { - insert(); - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.Unique)); - - DocumentCursor cursor = collection.find().sort("birthDay", SortOrder.Descending); - assertEquals(cursor.size(), 3); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, false)); - } - - @Test - public void testFindByIndexLimitAndSort() { - insert(); - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.Unique)); - - DocumentCursor cursor = collection.find(). - sort("birthDay", SortOrder.Descending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, false)); - - cursor = collection.find(). - sort("birthDay", SortOrder.Ascending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, true)); - - cursor = collection.find(). - sort("firstName", SortOrder.Ascending).skipLimit(0, 30); - assertEquals(cursor.size(), 3); - List nameList = new ArrayList<>(); - for (Document document : cursor) { - nameList.add(document.get("firstName", String.class)); - } - assertTrue(isSorted(nameList, true)); - } - - @Test - public void testFindAfterDroppedIndex() { - insert(); - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.Unique)); - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - - collection.dropIndex("firstName"); - cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - } - - @Test - public void testFindTextWithWildCard() { - insert(); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - - DocumentCursor cursor = collection.find(where("body").text("Lo")); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("body").text("Lo*")); - assertEquals(cursor.size(), 1); // Lorem - - cursor = collection.find(where("body").text("*rem")); - assertEquals(cursor.size(), 1); // lorem - - cursor = collection.find(where("body").text("*or*")); - assertEquals(cursor.size(), 2); - } - - @Test - public void testFindTextWithEmptyString() { - insert(); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - - DocumentCursor cursor = collection.find(where("body").text("")); - assertEquals(cursor.size(), 0); - } - - @Test - public void testFindWithOrIndexed() { - NitriteCollection collection = db.getCollection("testFindWithOrIndexed"); - Document doc1 = Document.createDocument("firstName", "John").put("lastName", "Doe"); - Document doc2 = Document.createDocument("firstName", "Jane").put("lastName", "Doe"); - Document doc3 = Document.createDocument("firstName", "Jonas").put("lastName", "Doe"); - Document doc4 = Document.createDocument("firstName", "Johan").put("lastName", "Day"); - - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.Unique)); - collection.createIndex("lastName", IndexOptions.indexOptions(IndexType.NonUnique)); - - collection.insert(doc1, doc2, doc3, doc4); - - DocumentCursor cursor = collection.find(where("firstName").eq("John").or(where("lastName").eq("Day"))); - assertEquals(cursor.size(), 2); - - List list = cursor.toList(); - assertEquals(list.size(), 2); - } - - @Test - public void testIssue45() { - NitriteCollection collection = db.getCollection("testIssue45"); - Faker faker = new Faker(); - String text1 = faker.lorem().paragraph() + " quick brown"; - String text2 = faker.lorem().paragraph() + " fox jump"; - String text3 = faker.lorem().paragraph() + " over lazy"; - String text4 = faker.lorem().paragraph() + " dog"; - - List list1 = Arrays.asList(text1, text2); - List list2 = Arrays.asList(text1, text2, text3); - List list3 = Arrays.asList(text2, text3); - List list4 = Arrays.asList(text1, text2, text3, text4); - - Document doc1 = Document.createDocument("firstName", "John").put("notes", list1); - Document doc2 = Document.createDocument("firstName", "Jane").put("notes", list2); - Document doc3 = Document.createDocument("firstName", "Jonas").put("notes", list3); - Document doc4 = Document.createDocument("firstName", "Johan").put("notes", list4); - - collection.createIndex("notes", IndexOptions.indexOptions(IndexType.Fulltext)); - collection.insert(doc1, doc2, doc3, doc4); - - DocumentCursor cursor = collection.find(where("notes").text("fox")); - assertEquals(cursor.size(), 4); - - cursor = collection.find(where("notes").text("dog")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("notes").text("lazy")); - assertEquals(cursor.size(), 3); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionFindNegativeTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionFindNegativeTest.java deleted file mode 100644 index 6791e75b9..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionFindNegativeTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.collection; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.rocksdb.BaseCollectionTest; -import org.junit.Test; - -import java.util.Date; -import java.util.List; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionFindNegativeTest extends BaseCollectionTest { - @Test(expected = ValidationException.class) - public void testFindFilterInvalidIndex() { - insert(); - collection.find(where("data.9").eq(4)).toList(); - } - - @Test(expected = ValidationException.class) - public void testFindOptionsNegativeOffset() { - insert(); - collection.find().skipLimit(-1, 1); - } - - @Test(expected = ValidationException.class) - public void testFindOptionsNegativeSize() { - insert(); - collection.find().skipLimit(0, -1); - } - - public void testFindOptionsInvalidOffset() { - insert(); - assertEquals(collection.find().skipLimit(10, 1).size(), 0); - } - - @Test(expected = ValidationException.class) - public void testFindInvalidSort() { - insert(); - collection.find().sort("data", SortOrder.Descending).toList(); - } - - @Test(expected = FilterException.class) - public void testFindTextFilterNonIndexed() { - insert(); - collection.find(where("body").text("Lorem")).toList(); - } - - @Test(expected = FilterException.class) - public void testFindWithRegexInvalidValue() { - insert(); - DocumentCursor cursor = collection.find(where("birthDay").regex("hello")); - assertEquals(cursor.size(), 1); - } - - @Test(expected = ValidationException.class) - public void testInvalidProjection() { - insert(); - DocumentCursor cursor = collection.find(where("birthDay").lte(new Date())). - sort("firstName", SortOrder.Ascending).skipLimit(0, 3); - - Document projection = createDocument("firstName", null) - .put("lastName", "ln2"); - - cursor.project(projection); - } - - @Test(expected = UnsupportedOperationException.class) - public void testToListAdd() { - insert(); - DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); - List documents = cursor.toList(); - documents.add(createDocument()); - } - - @Test(expected = UnsupportedOperationException.class) - public void testToListRemove() { - insert(); - DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); - List documents = cursor.toList(); - documents.clear(); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionFindTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionFindTest.java deleted file mode 100644 index 014e8aeee..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionFindTest.java +++ /dev/null @@ -1,862 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.collection; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.NullOrder; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.exceptions.IndexingException; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.rocksdb.BaseCollectionTest; -import org.joda.time.DateTime; -import org.junit.Test; - -import java.text.Collator; -import java.text.ParseException; -import java.util.*; -import java.util.stream.Collectors; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.common.Constants.*; -import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.$; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.rocksdb.TestUtil.isSorted; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.*; - -public class CollectionFindTest extends BaseCollectionTest { - - private static Document trimMeta(Document document) { - document.remove(DOC_ID); - document.remove(DOC_REVISION); - document.remove(DOC_MODIFIED); - document.remove(DOC_SOURCE); - return document; - } - - @Test - public void testFindAll() { - insert(); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - } - - @Test - public void testFindWithFilter() throws ParseException { - insert(); - - DocumentCursor cursor = collection.find(where("birthDay").gt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").gte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lte( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").lt( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").gt( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").gte( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .and(where("firstName").eq("fn1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12"))); - assertEquals(cursor.size(), 3); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1")).not()); - assertEquals(cursor.size(), 2); - - - cursor = collection.find(where("data.1").eq((byte) 4)); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").lt(4)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("firstName").notIn("fn1", "fn2")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(ALL.not()); - assertEquals(cursor.size(), 0); - } - - @Test - public void testFindWithSkipLimit() { - insert(); - - DocumentCursor cursor = collection.find().skipLimit(0, 1); - assertEquals(cursor.size(), 1); - - cursor = collection.find().skipLimit(1, 3); - assertEquals(cursor.size(), 2); - - cursor = collection.find().skipLimit(0, 30); - assertEquals(cursor.size(), 3); - - cursor = collection.find().skipLimit(2, 3); - assertEquals(cursor.size(), 1); - } - - @Test - public void testFindWithSkip() { - insert(); - - DocumentCursor cursor = collection.find().skip(0); - assertEquals(cursor.size(), 3); - - cursor = collection.find().skip(1); - assertEquals(cursor.size(), 2); - - cursor = collection.find().skip(30); - assertEquals(cursor.size(), 0); - - cursor = collection.find().skip(2); - assertEquals(cursor.size(), 1); - - boolean invalid = false; - try { - cursor = collection.find().skip(-1); - assertEquals(cursor.size(), 1); - } catch (ValidationException e) { - invalid = true; - } - assertTrue(invalid); - } - - @Test - public void testFindWithLimit() { - insert(); - - DocumentCursor cursor = collection.find().limit(0); - assertEquals(cursor.size(), 0); - - cursor = collection.find().limit(1); - assertEquals(cursor.size(), 1); - - boolean invalid = false; - try { - cursor = collection.find().limit(-1); - assertEquals(cursor.size(), 1); - } catch (ValidationException e) { - invalid = true; - } - assertTrue(invalid); - - cursor = collection.find().limit(30); - assertEquals(cursor.size(), 3); - } - - @Test - public void testFindSortAscending() { - insert(); - - DocumentCursor cursor = collection.find().sort("birthDay", SortOrder.Ascending); - assertEquals(cursor.size(), 3); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, true)); - } - - @Test - public void testFindSortDescending() { - insert(); - - DocumentCursor cursor = collection.find().sort("birthDay", SortOrder.Descending); - assertEquals(cursor.size(), 3); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, false)); - } - - @Test - public void testFindLimitAndSort() { - insert(); - - DocumentCursor cursor = collection.find(). - sort("birthDay", SortOrder.Descending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, false)); - - cursor = collection.find(). - sort("birthDay", SortOrder.Ascending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, true)); - - cursor = collection.find(). - sort("firstName", SortOrder.Ascending).skipLimit(0, 30); - assertEquals(cursor.size(), 3); - List nameList = new ArrayList<>(); - for (Document document : cursor) { - nameList.add(document.get("firstName", String.class)); - } - assertTrue(isSorted(nameList, true)); - } - - @Test - public void testFindSortOnNonExistingField() { - insert(); - DocumentCursor cursor = collection.find().sort("my-value", SortOrder.Descending); - assertEquals(cursor.size(), 3); - } - - @Test - public void testFindInvalidField() { - insert(); - DocumentCursor cursor = collection.find(where("myField").eq("myData")); - assertEquals(cursor.size(), 0); - } - - @Test - public void testFindInvalidFieldWithInvalidAccessor() { - insert(); - DocumentCursor cursor = collection.find(where("myField.0").eq("myData")); - assertEquals(cursor.size(), 0); - } - - @Test - public void testFindLimitAndSortInvalidField() { - insert(); - DocumentCursor cursor = collection.find(). - sort("birthDay2", SortOrder.Descending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - } - - @Test - public void testGetById() { - collection.insert(doc1); - NitriteId id = NitriteId.createId("1"); - Document document = collection.getById(id); - assertNull(document); - - document = collection.find().firstOrNull(); - - assertEquals(document.get(DOC_ID), document.getId().getIdValue()); - assertEquals(document.get("firstName"), "fn1"); - assertEquals(document.get("lastName"), "ln1"); - assertArrayEquals((byte[]) document.get("data"), new byte[]{1, 2, 3}); - assertEquals(document.get("body"), "a quick brown fox jump over the lazy dog"); - } - - @Test - public void testFindWithFilterAndOption() { - insert(); - DocumentCursor cursor = collection.find(where("birthDay").lte(new Date())). - sort("firstName", SortOrder.Ascending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - } - - @Test - public void testFindTextWithRegex() { - insert(); - DocumentCursor cursor = collection.find(where("body").regex("hello")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("body").regex("test")); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("body").regex("^hello$")); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("body").regex(".*")); - assertEquals(cursor.size(), 3); - } - - @Test - public void testProject() { - insert(); - DocumentCursor cursor = collection.find(where("birthDay").lte(new Date())). - sort("firstName", SortOrder.Ascending).skipLimit(0, 3); - int iteration = 0; - for (Document document : cursor) { - switch (iteration) { - case 0: - assertTrue(isSimilar(document, doc1, "firstName", "lastName", "birthDay", "data", "list", "body")); - break; - case 1: - assertTrue(isSimilar(document, doc2, "firstName", "lastName", "birthDay", "data", "list", "body")); - break; - case 2: - assertTrue(isSimilar(document, doc3, "firstName", "lastName", "birthDay", "data", "list", "body")); - break; - } - iteration++; - } - assertEquals(iteration, 3); - } - - @Test - public void testProjectWithCustomDocument() { - insert(); - DocumentCursor cursor = collection.find(where("birthDay").lte(new Date())). - sort("firstName", SortOrder.Ascending).skipLimit(0, 3); - - Document projection = createDocument("firstName", null) - .put("lastName", null); - - Iterable documents = cursor.project(projection); - int iteration = 0; - for (Document document : documents) { - assertTrue(document.containsKey("firstName")); - assertTrue(document.containsKey("lastName")); - - assertFalse(document.containsKey("_id")); - assertFalse(document.containsKey("birthDay")); - assertFalse(document.containsKey("data")); - assertFalse(document.containsKey("body")); - - switch (iteration) { - case 0: - assertEquals(document.get("firstName"), "fn1"); - assertEquals(document.get("lastName"), "ln1"); - break; - case 1: - assertEquals(document.get("firstName"), "fn2"); - assertEquals(document.get("lastName"), "ln2"); - break; - case 2: - assertEquals(document.get("firstName"), "fn3"); - assertEquals(document.get("lastName"), "ln2"); - break; - } - iteration++; - } - assertEquals(iteration, 3); - } - - @Test - public void testFindWithArrayEqual() { - insert(); - DocumentCursor ids = collection.find(where("data").eq(new byte[]{3, 4, 3})); - assertNotNull(ids); - assertEquals(ids.size(), 1); - } - - @Test - public void testFindWithArrayEqualFailForWrongCardinality() { - insert(); - DocumentCursor ids = collection.find(where("data").eq(new byte[]{4, 3, 3})); - assertNotNull(ids); - assertEquals(ids.size(), 0); - } - - @Test - public void testFindWithIterableEqual() { - insert(); - DocumentCursor ids = collection.find(where("list").eq( - new ArrayList() {{ - add("three"); - add("four"); - add("three"); - }})); - assertNotNull(ids); - assertEquals(ids.size(), 1); - } - - @Test - public void testFindWithIterableEqualFailForWrongCardinality() { - insert(); - DocumentCursor ids = collection.find(where("list").eq( - new ArrayList() {{ - add("four"); - add("three"); - add("three"); - }})); - assertNotNull(ids); - assertEquals(ids.size(), 0); - } - - @Test - public void testFindInArray() { - insert(); - DocumentCursor ids = collection.find(where("data").elemMatch($.gte(2).and($.lt(5)))); - assertNotNull(ids); - assertEquals(ids.size(), 3); - - ids = collection.find(where("data").elemMatch($.gt(2).or($.lte(5)))); - assertNotNull(ids); - assertEquals(ids.size(), 3); - - ids = collection.find(where("data").elemMatch($.gt(1).and($.lt(4)))); - assertNotNull(ids); - assertEquals(ids.size(), 2); - } - - @Test - public void testFindInList() { - insert(); - DocumentCursor ids = collection.find(where("list").elemMatch($.regex("three"))); - assertNotNull(ids); - assertEquals(ids.size(), 2); - - ids = collection.find(where("list").elemMatch($.regex("hello"))); - assertNotNull(ids); - assertEquals(ids.size(), 0); - - ids = collection.find(where("list").elemMatch($.regex("hello").not())); - assertNotNull(ids); - assertEquals(ids.size(), 2); - } - - @Test - public void testElemMatchFilter() { - Document doc1 = createDocument("productScores", new Document[]{ - createDocument("product", "abc").put("score", 10), - createDocument("product", "xyz").put("score", 5) - }).put("strArray", new String[]{"a", "b"}); - - Document doc2 = createDocument("productScores", new Document[]{ - createDocument("product", "abc").put("score", 8), - createDocument("product", "xyz").put("score", 7) - }).put("strArray", new String[]{"d", "e"}); - - Document doc3 = createDocument("productScores", new Document[]{ - createDocument("product", "abc").put("score", 7), - createDocument("product", "xyz").put("score", 8) - }).put("strArray", new String[]{"a", "f"}); - - NitriteCollection prodCollection = db.getCollection("prodScore"); - prodCollection.insert(doc1, doc2, doc3); - - List documentList = prodCollection.find(where("productScores") - .elemMatch(where("product").eq("xyz").and(where("score").gte(8)))).toList(); - - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").lte(8).not())).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("product").eq("xyz").or(where("score").gte(8)))).toList(); - assertEquals(documentList.size(), 3); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("product").eq("xyz"))).toList(); - assertEquals(documentList.size(), 3); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").gte(10))).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").gt(8))).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").lt(7))).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").lte(7))).toList(); - assertEquals(documentList.size(), 3); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").in(7, 8))).toList(); - assertEquals(documentList.size(), 2); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").notIn(7, 8))).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("product").regex("xyz"))).toList(); - assertEquals(documentList.size(), 3); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.eq("a"))).toList(); - assertEquals(documentList.size(), 2); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.eq("a").or($.eq("f").or($.eq("b"))).not())).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.gt("e"))).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.gte("e"))).toList(); - assertEquals(documentList.size(), 2); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.lte("b"))).toList(); - assertEquals(documentList.size(), 2); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.lt("a"))).toList(); - assertEquals(documentList.size(), 0); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.in("a", "f"))).toList(); - assertEquals(documentList.size(), 2); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.regex("a"))).toList(); - assertEquals(documentList.size(), 2); - - } - - @Test - public void testNotEqualFilter() { - Document document = createDocument("abc", "123"); - document.put("xyz", null); - - collection.insert(document); - DocumentCursor cursor = collection.find(where("abc").eq("123")); - assertEquals(cursor.size(), 1); - assertEquals(cursor.toList().size(), 1); - - cursor = collection.find(where("xyz").eq(null)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("abc").notEq(null)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("abc").notEq(null).and(where("xyz").eq(null))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("abc").eq(null).and(where("xyz").notEq(null))); - assertEquals(cursor.size(), 0); - - collection.remove(ALL); - - document = createDocument("field", "two"); - document.put(DOC_REVISION, 1482225343161L); - - collection.insert(document); - Document projection = collection.find( - where(DOC_REVISION).gte(1482225343160L) - .and(where(DOC_REVISION).lte(1482225343162L) - .and(where(DOC_REVISION).notEq(null)))) - .firstOrNull(); - - assertNull(projection); - } - - @Test - public void testFilterAll() { - DocumentCursor cursor = collection.find(ALL); - assertNotNull(cursor); - assertEquals(cursor.size(), 0); - - insert(); - cursor = collection.find(ALL); - assertNotNull(cursor); - assertEquals(cursor.size(), 3); - } - - @Test - public void testIssue72() { - NitriteCollection coll = db.getCollection("test"); - coll.createIndex("id", IndexOptions.indexOptions(IndexType.Unique)); - coll.createIndex("group", IndexOptions.indexOptions(IndexType.NonUnique)); - - coll.remove(ALL); - - Document doc = createDocument().put("id", "test-1").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - doc = createDocument().put("id", "test-2").put("group", "groupA").put("startTime", DateTime.now()); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - DocumentCursor cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending); - assertEquals(2, cursor.size()); - assertNull(cursor.toList().get(1).get("startTime")); - assertNotNull(cursor.toList().get(0).get("startTime")); - - cursor = coll.find(where("group").eq("groupA")).sort("startTime", SortOrder.Ascending); - assertEquals(2, cursor.size()); - assertNull(cursor.toList().get(0).get("startTime")); - assertNotNull(cursor.toList().get(1).get("startTime")); - } - - @Test - public void testIssue93() { - NitriteCollection coll = db.getCollection("orderByOnNullableColumn2"); - - coll.remove(ALL); - - Document doc = createDocument().put("id", "test-2").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - doc = createDocument().put("id", "test-1").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - DocumentCursor cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending); - assertEquals(2, cursor.size()); - } - - @Test - public void testNullOrderWithAllNull() { - NitriteCollection coll = db.getCollection("test"); - - coll.remove(ALL); - - Document doc = createDocument().put("id", "test-2").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - doc = createDocument().put("id", "test-1").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - DocumentCursor cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending); - assertEquals(2, cursor.size()); - - DocumentCursor cursor2 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.Default); - assertEquals(2, cursor2.size()); - - assertThat(cursor.toList(), is(cursor2.toList())); - - DocumentCursor cursor3 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.First); - assertEquals(2, cursor3.size()); - - assertThat(cursor.toList(), is(cursor3.toList())); - - DocumentCursor cursor4 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.Last); - assertEquals(2, cursor4.size()); - - assertThat(cursor.toList(), is(cursor4.toList())); - - DocumentCursor cursor5 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.Last); - assertEquals(2, cursor5.size()); - - assertThat(cursor.toList(), is(cursor5.toList())); - - DocumentCursor cursor6 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.First); - assertEquals(2, cursor6.size()); - - assertThat(cursor.toList(), is(cursor6.toList())); - - DocumentCursor cursor7 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.Default); - assertEquals(2, cursor7.size()); - - assertThat(cursor.toList(), is(cursor7.toList())); - } - - @Test - public void testNullOrder() { - NitriteCollection coll = db.getCollection("test"); - try { - coll.createIndex("startTime", IndexOptions.indexOptions(IndexType.NonUnique)); - } catch (IndexingException e) { - // ignore - } - - coll.remove(ALL); - - Document doc1 = createDocument().put("id", "test-1").put("group", "groupA"); - assertEquals(1, coll.insert(doc1).getAffectedCount()); - - Document doc2 = createDocument().put("id", "test-2").put("group", "groupA").put("startTime", DateTime.now()); - assertEquals(1, coll.insert(doc2).getAffectedCount()); - - Document doc3 = createDocument().put("id", "test-3").put("group", "groupA").put("startTime", DateTime.now().plusMinutes(1)); - assertEquals(1, coll.insert(doc3).getAffectedCount()); - - DocumentCursor cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc3, doc2, doc1), - equalTo(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.First); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc1, doc3, doc2), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.Default); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc3, doc2, doc1), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.Last); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc3, doc2, doc1), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.First); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc1, doc2, doc3), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.Default); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc1, doc2, doc3), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.Last); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc2, doc3, doc1), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - } - - @Test - public void testFindFilterInvalidAccessor() { - insert(); - DocumentCursor cursor = collection.find(where("lastName.name").eq("ln2")); - assertEquals(cursor.size(), 0); - } - - @Test - public void testIssue144() { - Document doc1 = createDocument().put("id", "test-1").put("fruit", "Apple"); - Document doc2 = createDocument().put("id", "test-2").put("fruit", "Ôrange"); - Document doc3 = createDocument().put("id", "test-3").put("fruit", "Pineapple"); - - NitriteCollection coll = db.getCollection("test"); - coll.insert(doc1, doc2, doc3); - - DocumentCursor cursor = coll.find().sort("fruit", SortOrder.Ascending, - Collator.getInstance(Locale.FRANCE)); - assertEquals(cursor.toList().get(1).get("fruit"), "Ôrange"); - } - - @Test - public void testIdSet() { - insert(); - DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("lastName").eq("ln1")); - assertEquals(cursor.size(), 1); - - Document byId = cursor.iterator().next(); - assertEquals(byId.get("lastName"), "ln1"); - } - - @Test - public void testCollectionField() { - Document document = createDocument("name", "John") - .put("tags", new Document[]{ - createDocument("type", "example").put("other", "value"), - createDocument("type", "another-example").put("other", "some-other-value") - }); - - NitriteCollection example = db.getCollection("example"); - example.insert(document); - - document = createDocument("name", "Jane") - .put("tags", new Document[]{ - createDocument("type", "example2").put("other", "value2"), - createDocument("type", "another-example2").put("other", "some-other-value2") - }); - example.insert(document); - - DocumentCursor cursor = example.find(where("tags").elemMatch(where("type").eq("example"))); - for (Document doc : cursor) { - assertNotNull(doc); - assertEquals(doc.get("name"), "John"); - } - } - - @Test - public void testBetweenFilter() { - Document doc1 = createDocument("age", 31).put("tag", "one"); - Document doc2 = createDocument("age", 32).put("tag", "two"); - Document doc3 = createDocument("age", 33).put("tag", "three"); - Document doc4 = createDocument("age", 34).put("tag", "four"); - Document doc5 = createDocument("age", 35).put("tag", "five"); - - NitriteCollection collection = db.getCollection("tag"); - collection.insert(doc1, doc2, doc3, doc4, doc5); - collection.createIndex("age", IndexOptions.indexOptions(IndexType.Unique)); - - DocumentCursor cursor = collection.find(where("age").between(31, 35)); - assertEquals(cursor.size(), 5); - - cursor = collection.find(where("age").between(31, 35, false)); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("age").between(31, 35, false, true)); - assertEquals(cursor.size(), 4); - - cursor = collection.find(where("age").between(31, 35, false).not()); - assertEquals(cursor.size(), 2); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionIndexNegativeTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionIndexNegativeTest.java deleted file mode 100644 index f340795ec..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionIndexNegativeTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.collection; - -import org.dizitart.no2.exceptions.IndexingException; -import org.dizitart.no2.exceptions.UniqueConstraintException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.rocksdb.BaseCollectionTest; -import org.junit.Test; - -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionIndexNegativeTest extends BaseCollectionTest { - - @Test(expected = UniqueConstraintException.class) - public void testCreateInvalidUniqueIndex() { - collection.createIndex("lastName", IndexOptions.indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("lastName")); - insert(); - } - - @Test(expected = UniqueConstraintException.class) - public void testCreateIndexOnArray() { - collection.createIndex("data", IndexOptions.indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("data")); - // data array field has repetition, so unique constraint exception - insert(); - } - - @Test - public void testCreateOnInvalidField() { - insert(); - collection.createIndex("my-value", IndexOptions.indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("my-value")); - } - - @Test(expected = IndexingException.class) - public void testCreateFullTextOnNonTextField() { - insert(); - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("birthDay")); - } - - @Test(expected = IndexingException.class) - public void testDropIndexOnNonIndexedField() { - collection.dropIndex("data"); - } - - @Test(expected = IndexingException.class) - public void testRebuildIndexInvalid() { - collection.rebuildIndex("unknown", true); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionIndexTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionIndexTest.java deleted file mode 100644 index 59c46cfeb..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionIndexTest.java +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.collection; - -import com.google.common.collect.Lists; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.IndexingException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexEntry; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.rocksdb.BaseCollectionTest; -import org.junit.Test; - -import java.util.Collection; -import java.util.Random; -import java.util.concurrent.Callable; - -import static org.awaitility.Awaitility.await; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionIndexTest extends BaseCollectionTest { - - @Test - public void testCreateIndex() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("firstName")); - - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - assertTrue(collection.hasIndex("lastName")); - - collection.createIndex("body", indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("body")); - - collection.createIndex("birthDay", null); - assertTrue(collection.hasIndex("birthDay")); - - insert(); - } - - @Test - public void testListIndexes() { - assertEquals(collection.listIndices().size(), 0); - - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("firstName")); - - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - assertTrue(collection.hasIndex("lastName")); - - collection.createIndex("body", indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("body")); - - assertEquals(collection.listIndices().size(), 3); - } - - @Test - public void testDropIndex() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("firstName")); - - collection.dropIndex("firstName"); - assertFalse(collection.hasIndex("firstName")); - } - - @Test - public void testDropAllIndexes() { - collection.dropAllIndices(); - - testCreateIndex(); - assertEquals(collection.listIndices().size(), 4); - - collection.dropAllIndices(); - assertEquals(collection.listIndices().size(), 0); - } - - @Test - public void testHasIndex() { - assertFalse(collection.hasIndex("lastName")); - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - assertTrue(collection.hasIndex("lastName")); - - assertFalse(collection.hasIndex("body")); - collection.createIndex("body", indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("body")); - } - - @Test - public void testDeleteWithIndex() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("body", indexOptions(IndexType.Fulltext)); - - insert(); - - WriteResult result = collection.remove(where("firstName").eq("fn1")); - assertEquals(result.getAffectedCount(), 1); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 2); - - result = collection.remove(where("body").text("Lorem")); - assertEquals(result.getAffectedCount(), 1); - - cursor = collection.find(); - assertEquals(cursor.size(), 1); - } - - @Test - public void testCreateIndexAsync() { - insert(); - collection.createIndex("body", indexOptions(IndexType.Fulltext, true)); - assertTrue(collection.isIndexing("body")); - - await().until(bodyIndexingCompleted()); - } - - @Test - public void testRebuildIndex() { - collection.createIndex("body", indexOptions(IndexType.Fulltext, false)); - insert(); - Collection indices = collection.listIndices(); - for (IndexEntry idx : indices) { - collection.rebuildIndex(idx.getField(), false); - } - } - - @Test - public void testRebuildIndexAsync() { - collection.createIndex("body", indexOptions(IndexType.Fulltext, true)); - insert(); - await().until(bodyIndexingCompleted()); - - Collection indices = collection.listIndices(); - for (IndexEntry idx : indices) { - collection.rebuildIndex(idx.getField(), true); - await().until(bodyIndexingCompleted()); - } - } - - @Test - public void testRebuildIndexOnRunningIndex() { - collection.createIndex("body", indexOptions(IndexType.Fulltext, false)); - Collection indices = collection.listIndices(); - IndexEntry idx = indices.iterator().next(); - insert(); - collection.rebuildIndex(idx.getField(), true); - - boolean error = false; - try { - collection.rebuildIndex(idx.getField(), true); - } catch (IndexingException ie) { - error = true; - } finally { - assertTrue(error); - await().until(bodyIndexingCompleted()); - } - } - - private Callable bodyIndexingCompleted() { - return () -> !collection.isIndexing("body"); - } - - @Test - public void testNullValueInIndexedField() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("birthDay", indexOptions(IndexType.NonUnique)); - insert(); - - Document document = createDocument("firstName", null) - .put("lastName", "ln1") - .put("birthDay", null) - .put("data", new byte[]{1, 2, 3}) - .put("list", Lists.newArrayList("one", "two", "three")) - .put("body", "a quick brown fox jump over the lazy dog"); - - collection.insert(document); - } - - @Test - public void testDropAllAndCreateIndex() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("firstName")); - collection.dropAllIndices(); - assertFalse(collection.hasIndex("firstName")); - - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("firstName")); - - collection = db.getCollection("test"); - assertTrue(collection.hasIndex("firstName")); - } - - @Test - public void testIssue178() { - collection.dropAllIndices(); - collection.remove(Filter.ALL); - - Document doc1 = createDocument("field", 5); - Document doc2 = createDocument("field", 4.3); - Document doc3 = createDocument("field", 0.03); - Document doc4 = createDocument("field", 4); - Document doc5 = createDocument("field", 5.0); - - collection.insert(doc1, doc2, doc3, doc4, doc5); - - DocumentCursor cursor = collection.find(where("field").eq(5)); - assertEquals(cursor.size(), 1); - - collection.createIndex("field", indexOptions(IndexType.NonUnique)); - - cursor = collection.find(where("field").eq(5)); - assertEquals(cursor.size(), 1); - } - - @Test - public void testIndexEvent() { - NitriteCollection collection = db.getCollection("index-test"); - Random random = new Random(); - for (int i = 0; i < 10000; i++) { - Document document = createDocument("first", random.nextInt()) - .put("second", random.nextDouble()); - collection.insert(document); - } - - collection.subscribe(eventInfo -> { - switch (eventInfo.getEventType()) { - case Insert: - fail("wrong event Insert"); - break; - case Update: - fail("wrong event Update"); - break; - case Remove: - fail("wrong event Remove"); - break; - case IndexStart: - case IndexEnd: - break; - } - assertTrue(eventInfo.getItem() instanceof String); - System.out.println(eventInfo.getEventType() + " for field " + eventInfo.getItem()); - }); - - collection.createIndex("first", indexOptions(IndexType.NonUnique)); - assertEquals(collection.find().size(), 10000); - - collection.createIndex("second", indexOptions(IndexType.NonUnique)); - assertEquals(collection.find().size(), 10000); - } - - @Test - public void testIndexAndSearchOnNullValues() { - NitriteCollection collection = db.getCollection("index-on-null"); - collection.insert(createDocument("first", null).put("second", 123).put("third", new Integer[]{1, 2, null})); - collection.insert(createDocument("first", "abcd").put("second", 456).put("third", new int[]{3, 1})); - collection.insert(createDocument("first", "xyz").put("second", 789).put("third", null)); - - collection.createIndex("first", indexOptions(IndexType.Unique)); - assertEquals(collection.find(where("first").eq(null)).size(), 1); - - collection.createIndex("third", indexOptions(IndexType.NonUnique)); - assertEquals(collection.find(where("third").eq(null)).size(), 2); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionInsertNegativeTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionInsertNegativeTest.java deleted file mode 100644 index e737708ab..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionInsertNegativeTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.collection; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.UniqueConstraintException; -import org.dizitart.no2.rocksdb.BaseCollectionTest; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionInsertNegativeTest extends BaseCollectionTest { - @Test(expected = UniqueConstraintException.class) - public void testMultipleInsert() { - WriteResult result = collection.insert(doc1, doc2, doc3); - assertEquals(result.getAffectedCount(), 3); - Document document = collection.find().firstOrNull(); - collection.insert(document); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionInsertTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionInsertTest.java deleted file mode 100644 index 93ef729ac..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionInsertTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.collection; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.rocksdb.BaseCollectionTest; -import org.junit.Test; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.common.Constants.DOC_ID; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -public class CollectionInsertTest extends BaseCollectionTest { - - @Test - public void testInsert() { - WriteResult result = collection.insert(doc1, doc2, doc3); - assertEquals(result.getAffectedCount(), 3); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - - for (Document document : cursor) { - assertNotNull(document.get("firstName")); - assertNotNull(document.get("lastName")); - assertNotNull(document.get("birthDay")); - assertNotNull(document.get("data")); - assertNotNull(document.get("body")); - assertNotNull(document.get(DOC_ID)); - } - } - - @Test - public void testInsertHeteroDocs() { - Document document = createDocument("test", "Nitrite Test"); - - WriteResult result = collection.insert(doc1, doc2, doc3, document); - assertEquals(result.getAffectedCount(), 4); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionJoinTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionJoinTest.java deleted file mode 100644 index c5f24ac93..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionJoinTest.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.collection; - -import lombok.extern.slf4j.Slf4j; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.Lookup; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.rocksdb.BaseCollectionTest; -import org.junit.Before; -import org.junit.Test; - -import java.util.Collection; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -@Slf4j -public class CollectionJoinTest extends BaseCollectionTest { - private NitriteCollection foreignCollection; - - @Before - @Override - public void setUp() { - try { - super.setUp(); - foreignCollection = db.getCollection("foreign"); - foreignCollection.remove(ALL); - - Document fdoc1 = createDocument("fName", "fn1") - .put("address", "ABCD Street") - .put("telephone", "123456789"); - - Document fdoc2 = createDocument("fName", "fn2") - .put("address", "XYZ Street") - .put("telephone", "000000000"); - - Document fdoc3 = createDocument("fName", "fn2") - .put("address", "Some other Street") - .put("telephone", "7893141321"); - - foreignCollection.insert(fdoc1, fdoc2, fdoc3); - } catch (Throwable t) { - log.error("Error while initializing test database", t); - } - } - - @Test - @SuppressWarnings("unchecked") - public void testJoinAll() { - insert(); - - Lookup lookup = new Lookup(); - lookup.setLocalField("firstName"); - lookup.setForeignField("fName"); - lookup.setTargetField("personalDetails"); - - RecordStream result = collection.find().join(foreignCollection.find(), lookup); - assertEquals(result.size(), 3); - - for (Document document : result) { - if (document.get("firstName") == "fn1") { - Collection personalDetails = (Collection) document.get("personalDetails"); - assertNotNull(personalDetails); - assertEquals(personalDetails.size(), 1); - Object[] details = personalDetails.toArray(); - assertEquals(((Document) details[0]).get("telephone"), "123456789"); - } else if (document.get("firstName") == "fn2") { - Collection personalDetails = (Collection) document.get("personalDetails"); - assertNotNull(personalDetails); - assertEquals(personalDetails.size(), 2); - Object[] details = personalDetails.toArray(); - for (Object o : details) { - Document d = (Document) o; - if (d.get("address").equals("XYZ Street")) { - assertEquals(d.get("telephone"), "000000000"); - } else { - assertEquals(d.get("telephone"), "7893141321"); - } - } - } else if (document.get("firstName") == "fn3") { - assertNull(document.get("personalDetails")); - } - System.out.println(document); - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionUpdateTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionUpdateTest.java deleted file mode 100644 index ed9e2f18c..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/CollectionUpdateTest.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.collection; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.UpdateOptions; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.NotIdentifiableException; -import org.dizitart.no2.exceptions.UniqueConstraintException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.rocksdb.BaseCollectionTest; -import org.junit.Test; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.*; - -public class CollectionUpdateTest extends BaseCollectionTest { - - @Test - public void testUpdate() { - insert(); - - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertEquals(document.get("lastName"), "ln1"); - } - - WriteResult updateResult = collection.update(where("firstName").eq("fn1"), - createDocument("lastName", "new-last-name")); - assertEquals(updateResult.getAffectedCount(), 1); - - cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertEquals(document.get("lastName"), "new-last-name"); - } - } - - @Test(expected = NotIdentifiableException.class) - public void testUpsertWithoutId() { - insert(); - Document update = createDocument("lastName", "ln4"); - WriteResult writeResult = collection.update(update, false); - assertEquals(writeResult.getAffectedCount(), 0); - assertEquals(collection.size(), 3); - } - - @Test - public void testUpsert() { - insert(); - assertEquals(collection.size(), 3); - - Document update = createDocument("lastName", "ln4"); - WriteResult writeResult = collection.update(update, true); - assertEquals(writeResult.getAffectedCount(), 1); - assertEquals(collection.size(), 4); - - Document document = collection.find(where("lastName").eq("ln4")) - .firstOrNull(); - assertTrue(isSimilar(document, update, "lastName")); - } - - @Test - public void testOptionUpsert() { - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - - WriteResult updateResult = collection.update(where("firstName").eq("fn1"), - doc1, UpdateOptions.updateOptions(true)); - assertEquals(updateResult.getAffectedCount(), 1); - - cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertTrue(isSimilar(document, doc1, "firstName", "lastName", "birthDay", "data", "list", "body")); - } - } - - @Test - public void testUpdateMultiple() { - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - - insert(); - - Document document = createDocument("lastName", "newLastName1"); - WriteResult updateResult = collection.update(where("firstName").eq("fn1").not(), - document); - assertEquals(updateResult.getAffectedCount(), 2); - - cursor = collection.find(where("lastName").eq("newLastName1")); - assertEquals(cursor.size(), 2); - } - - @Test - public void testUpdateWithOptionsUpsertFalse() { - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - - UpdateOptions updateOptions = new UpdateOptions(); - updateOptions.setInsertIfAbsent(false); - - WriteResult updateResult = collection.update(where("firstName").eq("fn1"), - doc1, updateOptions); - assertEquals(updateResult.getAffectedCount(), 0); - - cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - } - - @Test - public void testUpdateMultipleWithJustOnceFalse() { - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - - insert(); - - UpdateOptions updateOptions = new UpdateOptions(); - updateOptions.setJustOnce(false); - - Document document = createDocument("lastName", "newLastName1"); - WriteResult updateResult = collection.update(where("firstName").eq("fn1").not(), - document, updateOptions); - assertEquals(updateResult.getAffectedCount(), 2); - - cursor = collection.find(where("lastName").eq("newLastName1")); - assertEquals(cursor.size(), 2); - } - - @Test - public void testUpdateMultipleWithJustOnceTrue() { - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - - insert(); - - UpdateOptions updateOptions = new UpdateOptions(); - updateOptions.setJustOnce(true); - - Document document = createDocument("lastName", "newLastName1"); - collection.update(where("firstName").eq("fn1").not(), - document, updateOptions); - } - - @Test - public void testUpdateWithNewField() { - insert(); - - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertEquals(document.get("lastName"), "ln1"); - } - - WriteResult updateResult = collection.update(where("firstName").eq("fn1"), - createDocument("new-value", "new-value-value")); - assertEquals(updateResult.getAffectedCount(), 1); - - cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertEquals(document.get("new-value"), "new-value-value"); - } - } - - @Test - public void testUpdateInvalidFilter() { - insert(); - - DocumentCursor cursor = collection.find(where("lastName").eq("ln1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertEquals(document.get("firstName"), "fn1"); - } - - // to check if NitriteId is valid. - WriteResult updateResult = collection.update(where("some-value").eq("some-value"), - createDocument("lastName", "new-last-name")); - assertEquals(updateResult.getAffectedCount(), 0); - } - - @Test - public void updateAfterAttributeRemoval() { - NitriteCollection coll = db.getCollection("test_updateAfterAttributeRemoval"); - coll.remove(Filter.ALL); - - Document doc = createDocument().put("id", "test-1").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - Document savedDoc1 = coll.find().firstOrNull(); - assertNotNull(savedDoc1); - - Document clonedDoc1 = savedDoc1.clone(); - assertEquals(savedDoc1, clonedDoc1); - - clonedDoc1.put("group", null); -// clonedDoc1.remove("group"); - assertEquals(1, coll.update(clonedDoc1).getAffectedCount()); - - Document savedDoc2 = coll.find(Filter.ALL).firstOrNull(); - assertNotNull(savedDoc2); - assertNull(savedDoc2.get("group")); - } - - @Test(expected = NotIdentifiableException.class) - public void testUpdateWithoutId() { - NitriteCollection collection = db.getCollection("test"); - Document document = createDocument("test", "test123"); - collection.update(document); - } - - @Test(expected = NotIdentifiableException.class) - public void testRemoveWithoutId() { - NitriteCollection collection = db.getCollection("test"); - Document document = createDocument("test", "test123"); - collection.remove(document); - } - - @Test(expected = NitriteIOException.class) - public void testRegisterListenerAfterDrop() { - NitriteCollection collection = db.getCollection("test"); - collection.drop(); - collection.subscribe(changeInfo -> fail("should not happen")); - } - - @Test(expected = NitriteIOException.class) - public void testRegisterListenerAfterClose() { - NitriteCollection collection = db.getCollection("test"); - collection.close(); - collection.subscribe(changeInfo -> fail("should not happen")); - } - - @Test(expected = UniqueConstraintException.class) - public void testIssue151() { - Document doc1 = createDocument().put("id", "test-1").put("fruit", "Apple"); - Document doc2 = createDocument().put("id", "test-2").put("fruit", "Ôrange"); - NitriteCollection coll = db.getCollection("test"); - coll.insert(doc1, doc2); - - coll.createIndex("fruit", indexOptions(IndexType.Unique)); - - assertEquals(coll.find(where("fruit").eq("Apple")).size(), 1); - - Document doc3 = coll.find(where("id").eq("test-2")).firstOrNull(); - - doc3.put("fruit", "Apple"); - coll.update(doc3); - - assertEquals(coll.find(where("fruit").eq("Apple")).size(), 1); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/NitriteCollectionTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/NitriteCollectionTest.java deleted file mode 100644 index 8c48d8f48..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/NitriteCollectionTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.collection; - -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.rocksdb.AbstractTest; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee - */ -public class NitriteCollectionTest extends AbstractTest { - - @Test - public void testAttributes() { - NitriteCollection collection = db.getCollection("test"); - - Attributes attributes = new Attributes("test"); - collection.setAttributes(attributes); - - assertEquals(collection.getAttributes(), attributes); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/operation/DocumentCursorTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/operation/DocumentCursorTest.java deleted file mode 100644 index 8a76bd180..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/operation/DocumentCursorTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.collection.operation; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.rocksdb.AbstractTest; -import org.junit.Test; - -import java.util.Iterator; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee. - */ -public class DocumentCursorTest extends AbstractTest { - - @Test - public void testFindResult() { - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("first", "second")); - - DocumentCursor result = collection.find(); - assertNotNull(result); - } - - @Test(expected = InvalidOperationException.class) - public void testIteratorRemove() { - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("first", "second")); - - DocumentCursor cursor = collection.find(); - Iterator iterator = cursor.iterator(); - if (iterator.hasNext()) { - iterator.next(); - iterator.remove(); - } - } - - @Test - public void testValidateProjection() { - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("first", "second")); - - Document projection = createDocument("first", createDocument("second", null)); - RecordStream project = collection.find().project(projection); - assertNotNull(project); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/operation/JoinedDocumentStreamTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/operation/JoinedDocumentStreamTest.java deleted file mode 100644 index 40d94df00..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/collection/operation/JoinedDocumentStreamTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.collection.operation; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.Lookup; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.rocksdb.AbstractTest; -import org.junit.Test; - -import java.util.Iterator; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee - */ -public class JoinedDocumentStreamTest extends AbstractTest { - - @Test - public void testFindResult() { - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("first", "second")); - - RecordStream result = collection.find().join(collection.find(), new Lookup()); - assertNotNull(result); - } - - @Test(expected = InvalidOperationException.class) - public void testIteratorRemove() { - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("first", "second")); - - RecordStream cursor = collection.find().join(collection.find(), new Lookup()); - assertNotNull(cursor.toString()); - Iterator iterator = cursor.iterator(); - if (iterator.hasNext()) { - iterator.next(); - iterator.remove(); - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/common/event/EventTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/common/event/EventTest.java deleted file mode 100644 index 83ad508d6..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/common/event/EventTest.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.common.event; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.events.EventType; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.rocksdb.Retry; -import org.dizitart.no2.rocksdb.RocksDBModule; -import org.dizitart.no2.rocksdb.repository.data.Employee; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Collection; -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.awaitility.Awaitility.await; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.rocksdb.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.rocksdb.TestUtil.deleteFile; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -@RunWith(Parameterized.class) -public class EventTest { - @Parameterized.Parameter - public boolean isProtected = false; - - private final String fileName = getRandomTempDbFile(); - - private Nitrite db; - private ObjectRepository employeeRepository; - private SampleListenerCollection listener; - - @Parameterized.Parameters(name = "Protected = {0}") - public static Collection data() { - return Arrays.asList(new Object[][]{ - {false}, - {true}, - }); - } - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(fileName) - .build(); - - if (isProtected) { - db = Nitrite.builder() - .fieldSeparator(".") - .loadModule(storeModule) - .openOrCreate("test-user", "test-password"); - } else { - db = Nitrite.builder() - .fieldSeparator(".") - .loadModule(storeModule) - .openOrCreate(); - } - - try { - employeeRepository = db.getRepository(Employee.class); - listener = new SampleListenerCollection(); - employeeRepository.subscribe(listener); - } catch (Exception e) { - System.out.println("NitriteConfig - " + db.getConfig()); - throw e; - } - } - - @Test - public void testInsert() { - Employee employee = new Employee(); - employee.setEmpId(1L); - employeeRepository.insert(employee); - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); - assertEquals(listener.getAction(), EventType.Insert); - assertNotNull(listener.getItem()); - } - - @Test - public void testUpdate() { - Employee e = new Employee(); - e.setEmpId(1L); - e.setAddress("abcd"); - employeeRepository.insert(e); - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); - assertEquals(listener.getAction(), EventType.Insert); - assertNotNull(listener.getItem()); - - e.setAddress("xyz"); - employeeRepository.update(where("empId").eq(1L), e); - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Update)); - assertEquals(listener.getAction(), EventType.Update); - assertNotNull(listener.getItem()); - - Employee byId = employeeRepository.getById(1L); - assertEquals(byId.getAddress(), "xyz"); - } - - @Test - public void testUpsert() { - Employee e = new Employee(); - e.setEmpId(1L); - e.setAddress("abcd"); - - employeeRepository.update(where("empId").eq(1), e, true); - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); - assertEquals(listener.getAction(), EventType.Insert); - assertNotNull(listener.getItem()); - } - - @Test - public void testDelete() { - Employee e = new Employee(); - e.setEmpId(1L); - e.setAddress("abcd"); - - employeeRepository.insert(e); - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); - - employeeRepository.remove(where("empId").eq(1L)); - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Remove)); - - System.out.println("Action - " + listener.getAction()); - assertEquals(listener.getAction(), EventType.Remove); - assertNotNull(listener.getItem()); - } - - @Test - public void testDrop() { - employeeRepository.drop(); - assertNull(listener.getItem()); - } - - @Test - public void testClose() { - if (employeeRepository.isOpen()) { - employeeRepository.close(); - } - assertNull(listener.getItem()); - } - - @Test - public void testDeregister() { - employeeRepository.unsubscribe(listener); - Employee e = new Employee(); - e.setEmpId(1L); - e.setAddress("abcd"); - - employeeRepository.insert(e); - assertNull(listener.getAction()); - assertNull(listener.getItem()); - } - - @Test - public void testMultipleListeners() { - final AtomicInteger count = new AtomicInteger(0); - employeeRepository.subscribe(changeInfo -> count.incrementAndGet()); - - employeeRepository.subscribe(changeInfo -> count.incrementAndGet()); - - Employee e = new Employee(); - e.setEmpId(1L); - e.setAddress("abcd"); - employeeRepository.insert(e); - - await().atMost(1, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); - assertEquals(count.get(), 2); - } - - @Test - public void testSingleEventListener() { - final AtomicInteger count = new AtomicInteger(0); - employeeRepository.subscribe(changeInfo -> count.incrementAndGet()); - - employeeRepository = db.getRepository(Employee.class); - Employee e = new Employee(); - e.setEmpId(1L); - e.setAddress("abcd"); - employeeRepository.insert(e); - - await().atMost(2, TimeUnit.SECONDS).until(listenerPrepared(EventType.Insert)); - assertEquals(count.get(), 1); - } - - @After - public void clear() throws IOException { - if (employeeRepository != null) { - if (!employeeRepository.isDropped() - && employeeRepository.isOpen()) { - employeeRepository.remove(ALL); - employeeRepository.unsubscribe(listener); - employeeRepository.close(); - } - } - - if (db != null) { - db.commit(); - db.close(); - } - - deleteFile(fileName); - } - - private Callable listenerPrepared(final EventType action) { - return () -> listener.getAction() == action; - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/common/event/SampleListenerCollection.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/common/event/SampleListenerCollection.java deleted file mode 100644 index b4938756c..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/common/event/SampleListenerCollection.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.common.event; - -import lombok.Getter; -import org.dizitart.no2.collection.events.CollectionEventInfo; -import org.dizitart.no2.collection.events.CollectionEventListener; -import org.dizitart.no2.collection.events.EventType; - -/** - * @author Anindya Chatterjee. - */ -@Getter -class SampleListenerCollection implements CollectionEventListener { - private EventType action; - private Object item; - - @Override - public void onEvent(CollectionEventInfo eventInfo) { - if (eventInfo != null) { - this.action = eventInfo.getEventType(); - this.item = eventInfo.getItem(); - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/formatter/KryoObjectFormatterTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/formatter/KryoObjectFormatterTest.java index 4ccb88d69..eb44b2053 100644 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/formatter/KryoObjectFormatterTest.java +++ b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/formatter/KryoObjectFormatterTest.java @@ -1,19 +1,20 @@ package org.dizitart.no2.rocksdb.formatter; -import static org.junit.Assert.assertEquals; - import org.junit.Test; +import static org.junit.Assert.assertEquals; + public class KryoObjectFormatterTest { + @Test public void testEncode() { assertEquals(7, (new KryoObjectFormatter()).encode("object").length); - assertEquals(1, (new KryoObjectFormatter()).encode(null).length); + assertEquals(1, (new KryoObjectFormatter()).encode(null).length); } @Test public void testEncodeKey() { - assertEquals(1, (new KryoObjectFormatter()).encodeKey(null).length); + assertEquals(1, (new KryoObjectFormatter()).encodeKey(null).length); assertEquals(7, (new KryoObjectFormatter()).encodeKey("object").length); } } diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/migrate/MigrationTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/migrate/MigrationTest.java deleted file mode 100644 index 1ca248b9e..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/migrate/MigrationTest.java +++ /dev/null @@ -1,557 +0,0 @@ -package org.dizitart.no2.rocksdb.migrate; - -import com.github.javafaker.Faker; -import org.apache.commons.io.FileUtils; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.Constants; -import org.dizitart.no2.exceptions.MigrationException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.migration.Instruction; -import org.dizitart.no2.migration.Migration; -import org.dizitart.no2.migration.TypeConverter; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.rocksdb.Retry; -import org.dizitart.no2.rocksdb.RocksDBModule; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.File; -import java.io.IOException; -import java.util.UUID; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.rocksdb.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.rocksdb.TestUtil.createDb; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -public class MigrationTest { - private final String dbPath = getRandomTempDbFile(); - private Nitrite db; - private Faker faker; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - db = createDb(dbPath); - faker = new Faker(); - } - - @After - public void cleanUp() throws IOException { - if (!db.isClosed()) { - db.close(); - } - - FileUtils.deleteDirectory(new File(dbPath)); - } - - @Test - public void testRepositoryMigrate() { - ObjectRepository oldRepo = db.getRepository(OldClass.class, "demo1"); - for (int i = 0; i < 10; i++) { - OldClass old = new OldClass(); - old.setEmpId(String.valueOf(faker.number().randomNumber())); - old.setFirstName(faker.name().firstName()); - old.setLastName(faker.name().lastName()); - old.setUuid(UUID.randomUUID().toString()); - - OldClass.Literature literature = new OldClass.Literature(); - literature.setRatings((float) faker.number().randomDouble(2, 1, 5)); - literature.setText(faker.lorem().paragraph()); - old.setLiterature(literature); - - oldRepo.insert(old); - } - - db.close(); - - Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { - @Override - public void migrate(Instruction instruction) { - instruction.forDatabase() - .addPassword("test-user", "test-password"); - - instruction.forRepository(OldClass.class, "demo1") - .renameRepository("new", null) - .changeDataType("empId", (TypeConverter) Long::parseLong) - .changeIdField("uuid", "empId") - .deleteField("uuid") - .renameField("lastName", "familyName") - .addField("fullName", document -> document.get("firstName", String.class) + " " - + document.get("familyName", String.class)) - .dropIndex("firstName") - .dropIndex("literature.text") - .changeDataType("literature.ratings", (TypeConverter) Math::round); - } - }; - - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate("test-user", "test-password"); - - ObjectRepository newRepo = db.getRepository(NewClass.class); - assertEquals(newRepo.size(), 10); - assertTrue(db.listCollectionNames().isEmpty()); - assertTrue(db.listKeyedRepository().isEmpty()); - - assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 2); - } - - @Test - public void testCollectionMigrate() { - NitriteCollection collection = db.getCollection("test"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - document.put("bloodGroup", faker.name().bloodGroup()); - document.put("age", faker.number().randomDigit()); - - collection.insert(document); - } - - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.NonUnique)); - collection.createIndex("bloodGroup", IndexOptions.indexOptions(IndexType.NonUnique)); - db.close(); - - Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { - @Override - public void migrate(Instruction instruction) { - instruction.forDatabase() - .addPassword("test-user", "test-password"); - - instruction.forCollection("test") - .rename("testCollectionMigrate") - .deleteField("lastName"); - } - }; - - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate("test-user", "test-password"); - - collection = db.getCollection("testCollectionMigrate"); - assertTrue(collection.hasIndex("firstName")); - assertEquals(collection.size(), 10); - assertEquals(db.listCollectionNames().size(), 1); - assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 2); - db.close(); - - migration = new Migration(2, 3) { - @Override - public void migrate(Instruction instruction) { - instruction.forDatabase() - .changePassword("test-user", "test-password", "password"); - - instruction.forCollection("testCollectionMigrate") - .dropIndex("firstName") - .deleteField("bloodGroup") - .addField("name", document -> faker.name().fullName()) - .addField("address") - .addField("vehicles", 1) - .renameField("age", "ageGroup") - .createIndex("ageGroup", IndexType.NonUnique); - } - }; - - storeModule = RocksDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(3) - .addMigrations(migration) - .openOrCreate("test-user", "password"); - - collection = db.getCollection("testCollectionMigrate"); - assertEquals(collection.size(), 10); - assertEquals(db.listCollectionNames().size(), 1); - assertEquals((int) db.getDatabaseMetaData().getSchemaVersion(), 3); - - assertFalse(collection.hasIndex("firstName")); - assertTrue(collection.hasIndex("ageGroup")); - assertEquals(collection.find(where("age").notEq(null)).size(), 0); - } - - @Test(expected = MigrationException.class) - public void testOpenWithoutSchemaVersion() { - NitriteCollection collection = db.getCollection("test"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("test") - .rename("testOpenWithoutSchemaVersion") - .deleteField("lastName"); - } - }; - - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testOpenWithoutSchemaVersion"); - assertEquals(collection.size(), 10); - db.close(); - - storeModule = RocksDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(); - - collection = db.getCollection("testOpenWithoutSchemaVersion"); - assertEquals(collection.size(), 10); - } - - @Test - public void testDescendingSchema() { - NitriteCollection collection = db.getCollection("test"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("test") - .rename("testDescendingSchema") - .deleteField("lastName"); - } - }; - - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testDescendingSchema"); - assertEquals(collection.size(), 10); - db.close(); - - migration = new Migration(2, Constants.INITIAL_SCHEMA_VERSION) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("testDescendingSchema") - .rename("test"); - } - }; - - storeModule = RocksDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(1) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - } - - @Test - public void testMigrationWithoutVersion() { - NitriteCollection collection = db.getCollection("test"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration = new Migration(Constants.INITIAL_SCHEMA_VERSION, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("test") - .rename("testMigrationWithoutVersion") - .deleteField("lastName"); - } - }; - - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testMigrationWithoutVersion"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - } - - @Test - public void testWrongSchemaVersionNoMigration() { - NitriteCollection collection = db.getCollection("testWrongSchemaVersionNoMigration"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration = new Migration(1, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("testWrongSchemaVersionNoMigration") - .rename("test") - .deleteField("lastName"); - } - }; - - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testWrongSchemaVersionNoMigration"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - - migration = new Migration(2, 3) { - @Override - public void migrate(Instruction instruction) { - instruction.forCollection("test") - .rename("testWrongSchemaVersionNoMigration"); - } - }; - - storeModule = RocksDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testWrongSchemaVersionNoMigration"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - } - - @Test - public void testReOpenAfterMigration() { - NitriteCollection collection = db.getCollection("testReOpenAfterMigration"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration = new Migration(1, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("testReOpenAfterMigration") - .rename("test") - .deleteField("lastName"); - } - }; - - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testReOpenAfterMigration"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration) - .openOrCreate(); - - collection = db.getCollection("testReOpenAfterMigration"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - db.close(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .openOrCreate(); - - collection = db.getCollection("testReOpenAfterMigration"); - assertEquals(collection.size(), 0); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - } - - @Test - public void testMultipleMigrations() { - NitriteCollection collection = db.getCollection("testMultipleMigrations"); - for (int i = 0; i < 10; i++) { - Document document = Document.createDocument(); - document.put("firstName", faker.name().firstName()); - document.put("lastName", faker.name().lastName()); - - collection.insert(document); - } - db.close(); - - Migration migration1 = new Migration(1, 2) { - @Override - public void migrate(Instruction instruction) { - - instruction.forCollection("testMultipleMigrations") - .rename("test"); - } - }; - - Migration migration2 = new Migration(2, 3) { - @Override - public void migrate(Instruction instruction) { - instruction.forCollection("test") - .addField("fullName", "Dummy Name"); - } - }; - - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(2) - .addMigrations(migration1, migration2) - .openOrCreate(); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - assertEquals(collection.find(where("fullName").eq("Dummy Name")).size(), 0); - db.close(); - - Migration migration3 = new Migration(3, 4) { - @Override - public void migrate(Instruction instruction) { - instruction.forCollection("test") - .addField("age", 10); - } - }; - - storeModule = RocksDBModule.withConfig() - .filePath(dbPath) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .schemaVersion(4) - .addMigrations(migration1, migration2, migration3) - .openOrCreate(); - - collection = db.getCollection("test"); - assertEquals(collection.size(), 10); - assertEquals(collection.find(where("fullName").eq("Dummy Name")).size(), 10); - assertEquals(collection.find(where("age").eq(10)).size(), 10); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/migrate/NewClass.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/migrate/NewClass.java deleted file mode 100644 index 92035e98f..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/migrate/NewClass.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.dizitart.no2.rocksdb.migrate; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Entity; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; - -/** - * @author Anindya Chatterjee - */ -@Data -@Entity(value = "new", indices = { - @Index(value = "familyName", type = IndexType.NonUnique), - @Index(value = "fullName", type = IndexType.NonUnique), - @Index(value = "literature.ratings", type = IndexType.NonUnique), -}) -public class NewClass implements Mappable { - @Id - private Long empId; - private String firstName; - private String familyName; - private String fullName; - private Literature literature; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("empId", empId) - .put("firstName", firstName) - .put("familyName", familyName) - .put("fullName", fullName) - .put("literature", literature.write(mapper)); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - empId = document.get("empId", Long.class); - firstName = document.get("firstName", String.class); - familyName = document.get("familyName", String.class); - fullName = document.get("fullName", String.class); - - Document doc = document.get("literature", Document.class); - literature = new Literature(); - literature.read(mapper, doc); - } - - @Data - public static class Literature implements Mappable { - private String text; - private Integer ratings; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("text", text) - .put("ratings", ratings); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - text = document.get("text", String.class); - ratings = document.get("ratings", Integer.class); - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/migrate/OldClass.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/migrate/OldClass.java deleted file mode 100644 index a2eb259ba..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/migrate/OldClass.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.dizitart.no2.rocksdb.migrate; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Entity; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; - -/** - * @author Anindya Chatterjee - */ -@Data -@Entity(value = "old", indices = { - @Index(value = "firstName", type = IndexType.NonUnique), - @Index(value = "lastName", type = IndexType.NonUnique), - @Index(value = "literature.text", type = IndexType.Fulltext), - @Index(value = "literature.ratings", type = IndexType.NonUnique), -}) -public class OldClass implements Mappable { - @Id - private String uuid; - private String empId; - private String firstName; - private String lastName; - private Literature literature; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("empId", empId) - .put("uuid", uuid) - .put("firstName", firstName) - .put("lastName", lastName) - .put("literature", literature.write(mapper)); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - empId = document.get("empId", String.class); - uuid = document.get("uuid", String.class); - firstName = document.get("firstName", String.class); - lastName = document.get("lastName", String.class); - - Document doc = document.get("literature", Document.class); - literature = new Literature(); - literature.read(mapper, doc); - } - - @Data - public static class Literature implements Mappable { - private String text; - private Float ratings; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("text", text) - .put("ratings", ratings); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - text = document.get("text", String.class); - ratings = document.get("ratings", Float.class); - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/BaseObjectRepositoryTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/BaseObjectRepositoryTest.java deleted file mode 100644 index 80df40433..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/BaseObjectRepositoryTest.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.rocksdb.Retry; -import org.dizitart.no2.rocksdb.RocksDBModule; -import org.dizitart.no2.rocksdb.repository.data.*; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Collection; - -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.rocksdb.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.rocksdb.TestUtil.deleteFile; - -@RunWith(value = Parameterized.class) -public abstract class BaseObjectRepositoryTest { - @Parameterized.Parameter - public boolean isProtected = false; - - protected Nitrite db; - ObjectRepository companyRepository; - ObjectRepository employeeRepository; - ObjectRepository aObjectRepository; - ObjectRepository cObjectRepository; - private final String fileName = getRandomTempDbFile(); - - @Parameterized.Parameters(name = "Protected = {0}") - public static Collection data() { - return Arrays.asList(new Object[][]{ - {false}, - {true}, - }); - } - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - openDb(); - - companyRepository = db.getRepository(Company.class); - employeeRepository = db.getRepository(Employee.class); - - aObjectRepository = db.getRepository(ClassA.class); - cObjectRepository = db.getRepository(ClassC.class); - - for (int i = 0; i < 10; i++) { - Company company = DataGenerator.generateCompanyRecord(); - companyRepository.insert(company); - Employee employee = DataGenerator.generateEmployee(); - employee.setEmpId((long) i + 1); - employeeRepository.insert(employee); - - aObjectRepository.insert(ClassA.create(i + 50)); - cObjectRepository.insert(ClassC.create(i + 30)); - } - } - - protected void openDb() { - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(fileName) - .build(); - - NitriteBuilder nitriteBuilder = Nitrite.builder() - .fieldSeparator(".") - .loadModule(storeModule); - - if (isProtected) { - db = nitriteBuilder.openOrCreate("test-user", "test-password"); - } else { - db = nitriteBuilder.openOrCreate(); - } - } - - @After - public void clear() throws IOException { - if (companyRepository != null && !companyRepository.isDropped()) { - companyRepository.remove(ALL); - } - - if (employeeRepository != null && !employeeRepository.isDropped()) { - employeeRepository.remove(ALL); - } - - if (aObjectRepository != null && !aObjectRepository.isDropped()) { - aObjectRepository.remove(ALL); - } - - if (cObjectRepository != null && !cObjectRepository.isDropped()) { - cObjectRepository.remove(ALL); - } - - if (db != null && !db.isClosed()) { - db.commit(); - db.close(); - } - - deleteFile(fileName); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/CustomFieldSeparatorTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/CustomFieldSeparatorTest.java deleted file mode 100644 index c7eb5c5dc..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/CustomFieldSeparatorTest.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteConfig; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; -import org.dizitart.no2.rocksdb.Retry; -import org.dizitart.no2.rocksdb.RocksDBModule; -import org.dizitart.no2.rocksdb.repository.data.Company; -import org.dizitart.no2.rocksdb.repository.data.Note; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.io.Serializable; -import java.util.Date; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.rocksdb.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.rocksdb.TestUtil.deleteFile; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee - */ -public class CustomFieldSeparatorTest { - private final String fileName = getRandomTempDbFile(); - private ObjectRepository repository; - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(fileName) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(":") - .openOrCreate(); - - repository = db.getRepository(EmployeeForCustomSeparator.class); - } - - @After - public void reset() throws IOException { - (new NitriteConfig()).fieldSeparator("."); - db.close(); - deleteFile(fileName); - } - - @Test - public void testFieldSeparator() { - assertEquals(NitriteConfig.getFieldSeparator(), ":"); - } - - @Test - public void testFindByEmbeddedField() { - EmployeeForCustomSeparator employee = new EmployeeForCustomSeparator(); - employee.setCompany(new Company()); - employee.setEmployeeNote(new Note()); - - employee.setEmpId(123L); - employee.setJoinDate(new Date()); - employee.setBlob(new byte[0]); - employee.setAddress("Dummy address"); - - employee.getCompany().setCompanyId(987L); - employee.getCompany().setCompanyName("Dummy Company"); - employee.getCompany().setDateCreated(new Date()); - - employee.getEmployeeNote().setNoteId(567L); - employee.getEmployeeNote().setText("Dummy Note"); - - repository.insert(employee); - - assertEquals(repository.find(where("employeeNote.text").eq("Dummy Note")).size(), 0); - assertEquals(repository.find(where("employeeNote:text").text("Dummy Note")).size(), 1); - - assertEquals(repository.find(where("company.companyName").eq("Dummy Company")).size(), 0); - assertEquals(repository.find(where("company:companyName").eq("Dummy Company")).size(), 1); - } - - @ToString - @EqualsAndHashCode - @Indices({ - @Index(value = "joinDate", type = IndexType.NonUnique), - @Index(value = "address", type = IndexType.Fulltext), - @Index(value = "employeeNote:text", type = IndexType.Fulltext) - }) - public static class EmployeeForCustomSeparator implements Serializable, Mappable { - @Id - @Getter - @Setter - private Long empId; - - @Getter - @Setter - private Date joinDate; - - @Getter - @Setter - private String address; - - @Getter - @Setter - private Company company; - - @Getter - @Setter - private byte[] blob; - - @Getter - @Setter - private Note employeeNote; - - EmployeeForCustomSeparator() { - } - - public EmployeeForCustomSeparator(EmployeeForCustomSeparator copy) { - empId = copy.empId; - joinDate = copy.joinDate; - address = copy.address; - company = copy.company; - blob = copy.blob; - employeeNote = copy.employeeNote; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument().put("empId", empId) - .put("joinDate", joinDate) - .put("address", address) - .put("blob", blob) - .put("company", company.write(mapper)) - .put("employeeNote", employeeNote.write(mapper)); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - empId = document.get("empId", Long.class); - joinDate = document.get("joinDate", Date.class); - address = document.get("address", String.class); - blob = document.get("blob", byte[].class); - employeeNote = new Note(); - Document doc = document.get("employeeNote", Document.class); - employeeNote.read(mapper, doc); - company = new Company(); - doc = document.get("company", Document.class); - company.read(mapper, doc); - } - } - -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/InternalClass.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/InternalClass.java deleted file mode 100644 index ec5bda278..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/InternalClass.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Data -class InternalClass implements Mappable { - @Id - private long id; - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("id", id) - .put("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Long.class); - name = document.get("name", String.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/NitriteIdAsIdTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/NitriteIdAsIdTest.java deleted file mode 100644 index 350632c9e..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/NitriteIdAsIdTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository; - -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.common.util.Iterables; -import org.dizitart.no2.exceptions.InvalidIdException; -import org.dizitart.no2.rocksdb.AbstractTest; -import org.dizitart.no2.rocksdb.repository.data.WithNitriteId; -import org.dizitart.no2.repository.Cursor; -import org.dizitart.no2.repository.ObjectRepository; -import org.junit.Before; -import org.junit.Test; - -import java.text.ParseException; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee - */ -public class NitriteIdAsIdTest extends AbstractTest { - private ObjectRepository repo; - - @Before - public void before() { - repo = db.getRepository(WithNitriteId.class); - } - - - @Test - public void testNitriteIdField() { - WithNitriteId item1 = new WithNitriteId(); - item1.name = "first"; - - WithNitriteId item2 = new WithNitriteId(); - item2.name = "second"; - - repo.insert(item1, item2); - - Cursor cursor = repo.find(); - for (WithNitriteId withNitriteId : cursor) { - System.out.println(withNitriteId.name); - assertNotNull(withNitriteId.idField); - } - - WithNitriteId withNitriteId = cursor.firstOrNull(); - withNitriteId.name = "third"; - - NitriteId id = withNitriteId.idField; - repo.update(withNitriteId); - - WithNitriteId byId = repo.getById(id); - assertEquals(withNitriteId, byId); - assertEquals(repo.size(), 2); - } - - @Test(expected = InvalidIdException.class) - public void setIdDuringInsert() { - WithNitriteId item1 = new WithNitriteId(); - item1.name = "first"; - item1.idField = NitriteId.newId(); - - repo.insert(item1); - } - - @Test - public void changeIdDuringUpdate() { - WithNitriteId item2 = new WithNitriteId(); - item2.name = "second"; - WriteResult result = repo.insert(item2); - NitriteId nitriteId = Iterables.firstOrNull(result); - WithNitriteId byId = repo.getById(nitriteId); - byId.idField = NitriteId.newId(); - - result = repo.update(byId); - assertEquals(result.getAffectedCount(), 0); - assertEquals(repo.size(), 1); - } - -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/ObjectCursorTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/ObjectCursorTest.java deleted file mode 100644 index cc8a4a123..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/ObjectCursorTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository; - -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.rocksdb.repository.data.Employee; -import org.dizitart.no2.repository.Cursor; -import org.junit.Test; - -import java.util.AbstractCollection; - -/** - * @author Anindya Chatterjee - */ -public class ObjectCursorTest extends BaseObjectRepositoryTest { - - @Test(expected = ValidationException.class) - public void testProjectForInterface() { - Cursor cursor = employeeRepository.find(); - cursor.project(Comparable.class); - } - - @Test(expected = ValidationException.class) - public void testProjectForPrimitive() { - Cursor cursor = employeeRepository.find(); - cursor.project(int.class); - } - - @Test(expected = ValidationException.class) - public void testProjectForArray() { - Cursor cursor = employeeRepository.find(); - cursor.project(String[].class); - } - - @Test(expected = ValidationException.class) - public void testProjectForAbstractClass() { - Cursor cursor = employeeRepository.find(); - cursor.project(AbstractCollection.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/ObjectRepositoryNegativeTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/ObjectRepositoryNegativeTest.java deleted file mode 100644 index db86865f7..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/ObjectRepositoryNegativeTest.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository; - -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.*; -import org.dizitart.no2.rocksdb.AbstractTest; -import org.dizitart.no2.rocksdb.repository.data.*; -import org.dizitart.no2.repository.ObjectRepository; -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class ObjectRepositoryNegativeTest extends AbstractTest { - - @Test(expected = ObjectMappingException.class) - public void testWithCircularReference() { - ObjectRepository repository = db.getRepository(WithCircularReference.class); - - WithCircularReference parent = new WithCircularReference(); - parent.setName("parent"); - WithCircularReference object = new WithCircularReference(); - object.setName("test"); - object.setParent(parent); - // circular reference - parent.setParent(object); - - WriteResult result = repository.insert(object); - for (NitriteId id : result) { - WithCircularReference instance = repository.getById(id); - assertEquals(instance.getName(), object.getName()); - assertEquals(instance.getParent().getName(), object.getParent().getName()); - } - } - - @Test(expected = ObjectMappingException.class) - public void testWithCustomConstructor() { - ObjectRepository repository = db.getRepository(WithCustomConstructor.class); - - WithCustomConstructor object = new WithCustomConstructor("test", 2L); - - WriteResult result = repository.insert(object); - for (NitriteId id : result) { - WithCustomConstructor instance = repository.getById(id); - assertEquals(object.getName(), instance.getName()); - assertEquals(object.getNumber(), instance.getNumber()); - } - } - - @Test(expected = InvalidIdException.class) - public void testWithEmptyStringId() { - ObjectRepository repository = db.getRepository(WithEmptyStringId.class); - WithEmptyStringId object = new WithEmptyStringId(); - object.setName(""); // empty id value - - WriteResult result = repository.insert(object); - for (NitriteId id : result) { - WithEmptyStringId instance = repository.getById(id); - assertEquals(instance, object); - } - } - - @Test(expected = InvalidIdException.class) - public void testWithNullId() { - ObjectRepository repository = db.getRepository(WithNullId.class); - WithNullId object = new WithNullId(); - - WriteResult result = repository.insert(object); - for (NitriteId id : result) { - WithNullId instance = repository.getById(id); - assertEquals(instance, object); - } - } - - @Test(expected = ValidationException.class) - public void testWithValueTypeRepository() { - ObjectRepository repository = db.getRepository(String.class); - repository.insert("test"); - } - - @Test(expected = InvalidOperationException.class) - public void testFindResultRemove() { - ObjectRepository repository = db.getRepository(Employee.class); - repository.insert(DataGenerator.generateEmployee()); - RecordStream result = repository.find(); - result.iterator().remove(); - } - - @Test(expected = InvalidOperationException.class) - public void testWithObjectId() { - ObjectRepository repository = db.getRepository(WithObjectId.class); - WithOutId id = new WithOutId(); - id.setName("test"); - id.setNumber(1); - - WithObjectId object = new WithObjectId(); - object.setWithOutId(id); - repository.insert(object); - } - - @Test(expected = NotIdentifiableException.class) - public void testUpdateNoId() { - ObjectRepository repository = db.getRepository(WithOutId.class); - WithOutId object = new WithOutId(); - object.setName("name"); - object.setNumber(1L); - repository.update(object); - } - - @Test(expected = NotIdentifiableException.class) - public void testRemoveNoId() { - ObjectRepository repository = db.getRepository(WithOutId.class); - WithOutId object = new WithOutId(); - object.setName("name"); - object.setNumber(1L); - repository.remove(object); - } - - @Test(expected = ValidationException.class) - public void testProjectionFailedInstantiate() { - ObjectRepository repository = db.getRepository(WithOutId.class); - WithOutId object = new WithOutId(); - object.setName("name"); - object.setNumber(1L); - repository.insert(object); - - RecordStream project = repository.find().project(NitriteId.class); - assertNull(project.toList()); - } - - @Test(expected = ValidationException.class) - public void testNullInsert() { - ObjectRepository repository = db.getRepository(WithOutId.class); - repository.insert(null); - } - - @Test(expected = InvalidIdException.class) - public void testGetByNullId() { - ObjectRepository repository = db.getRepository(WithPublicField.class); - WithPublicField object = new WithPublicField(); - object.name = "test"; - object.number = 2; - - repository.insert(object); - WithPublicField instance = repository.getById(null); - assertEquals(object.name, instance.name); - assertEquals(object.number, instance.number); - } - - @Test - public void testExternalNitriteId() { - ObjectRepository repository = db.getRepository(WithNitriteId.class); - WithNitriteId obj = new WithNitriteId(); - NitriteId id = NitriteId.createId("1"); - obj.setIdField(id); - obj.setName("testExternalNitriteId"); - WriteResult result = repository.update(obj, true); - - obj = new WithNitriteId(); - id = result.iterator().next(); - obj.setIdField(id); - obj.setName("testExternalNitriteId"); - result = repository.update(obj, true); - assertNotEquals(id.getIdValue(), result.iterator().next().getIdValue()); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/ObjectRepositoryTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/ObjectRepositoryTest.java deleted file mode 100644 index b6f59187c..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/ObjectRepositoryTest.java +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository; - -import com.github.javafaker.Faker; -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.Cursor; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Entity; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.rocksdb.AbstractTest; -import org.dizitart.no2.rocksdb.repository.data.*; -import org.junit.Test; - -import java.util.Date; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.awaitility.Awaitility.await; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class ObjectRepositoryTest extends AbstractTest { - - @Test - public void testWithClassField() { - ObjectRepository repository = db.getRepository(WithClassField.class); - - WithClassField object = new WithClassField(); - object.setName("test"); - object.setClazz(String.class); - - repository.insert(object); - WithClassField instance = repository.getById("test"); - assertEquals(instance.getName(), object.getName()); - assertEquals(instance.getClazz(), object.getClazz()); - } - - @Test - public void testWithFinalField() { - ObjectRepository repository = db.getRepository(WithFinalField.class); - WithFinalField object = new WithFinalField(); - object.setName("test"); - - repository.insert(object); - for (WithFinalField instance : repository.find()) { - assertEquals(object.getName(), instance.getName()); - assertEquals(object.getNumber(), instance.getNumber()); - } - } - - @Test - public void testWithOutGetterSetter() { - ObjectRepository repository = db.getRepository(WithOutGetterSetter.class); - WithOutGetterSetter object = new WithOutGetterSetter(); - - repository.insert(object); - for (WithOutGetterSetter instance : repository.find()) { - assertEquals(object, instance); - } - } - - @Test - public void testWithOutId() { - ObjectRepository repository = db.getRepository(WithOutId.class); - WithOutId object = new WithOutId(); - object.setName("test"); - object.setNumber(2); - - repository.insert(object); - for (WithOutId instance : repository.find()) { - assertEquals(object.getName(), instance.getName()); - assertEquals(object.getNumber(), instance.getNumber()); - } - } - - @Test - public void testWithPublicField() { - ObjectRepository repository = db.getRepository(WithPublicField.class); - WithPublicField object = new WithPublicField(); - object.name = "test"; - object.number = 2; - - repository.insert(object); - WithPublicField instance = repository.getById("test"); - assertEquals(object.name, instance.name); - assertEquals(object.number, instance.number); - } - - @Test - public void testWithTransientField() { - ObjectRepository repository = db.getRepository(WithTransientField.class); - WithTransientField object = new WithTransientField(); - object.setNumber(2); - object.setName("test"); - - repository.insert(object); - WithTransientField instance = repository.getById(2L); - assertNotEquals(object.getName(), instance.getName()); - assertNull(instance.getName()); - assertEquals(object.getNumber(), instance.getNumber()); - } - - @Test - public void testWriteThousandRecords() { - int count = 5000; - - ObjectRepository repository = db.getRepository(StressRecord.class); - - for (int i = 0; i < count; i++) { - StressRecord record = new StressRecord(); - record.setFirstName(UUID.randomUUID().toString()); - record.setFailed(false); - record.setLastName(UUID.randomUUID().toString()); - record.setProcessed(false); - - repository.insert(record); - } - - Cursor cursor - = repository.find(where("failed").eq(false)); - - for (StressRecord record : cursor) { - record.setProcessed(true); - repository.update(where("firstName").eq(record.getFirstName()), record); - } - } - - @Test - public void testWithPackagePrivateClass() { - ObjectRepository repository = db.getRepository(InternalClass.class); - InternalClass internalClass = new InternalClass(); - internalClass.setId(1); - internalClass.setName("name"); - - repository.insert(internalClass); - InternalClass instance = repository.getById((long) 1); - assertEquals(internalClass.getName(), instance.getName()); - assertEquals(internalClass.getId(), instance.getId()); - } - - @Test - public void testWithPrivateConstructor() { - ObjectRepository repository = - db.getRepository(WithPrivateConstructor.class); - - WithPrivateConstructor object = WithPrivateConstructor.create("test", 2L); - repository.insert(object); - for (WithPrivateConstructor instance : repository.find()) { - assertEquals(object, instance); - } - } - - @Test - public void testWithDateAsId() { - ObjectRepository repository = db.getRepository(WithDateId.class); - - WithDateId object1 = new WithDateId(); - object1.setId(new Date(1482773634L)); - object1.setName("first date"); - repository.insert(object1); - - WithDateId object2 = new WithDateId(); - object2.setName("second date"); - object2.setId(new Date(1482773720L)); - repository.insert(object2); - - assertEquals(repository.find(where("id").eq(new Date(1482773634L))) - .firstOrNull(), object1); - assertEquals(repository.find(where("id").eq(new Date(1482773720L))) - .firstOrNull(), object2); - } - - @Test - public void testWithIdInheritance() { - ObjectRepository repository = db.getRepository(ChildClass.class); - assertTrue(repository.hasIndex("id")); - assertTrue(repository.hasIndex("date")); - assertTrue(repository.hasIndex("text")); - - ChildClass childClass = new ChildClass(); - childClass.setName("first"); - childClass.setDate(new Date(100000L)); - childClass.setId(1L); - childClass.setText("I am first class"); - repository.insert(childClass); - - childClass = new ChildClass(); - childClass.setName("seconds"); - childClass.setDate(new Date(100001L)); - childClass.setId(2L); - childClass.setText("I am second class"); - repository.insert(childClass); - - childClass = new ChildClass(); - childClass.setName("third"); - childClass.setDate(new Date(100002L)); - childClass.setId(3L); - childClass.setText("I am third class"); - repository.insert(childClass); - - assertEquals(repository.find(where("text").text("class")).size(), 3); - assertEquals(repository.find(where("text").text("second")).size(), 0); // filtered in stop words - assertEquals(repository.find(where("date").eq(new Date(100000L))).size(), 1); - assertEquals(repository.find(where("id").eq(1L)).size(), 1); - } - - @Test - public void testAttributes() { - ObjectRepository repository = db.getRepository(WithDateId.class); - Attributes attributes = new Attributes(repository.getDocumentCollection().getName()); - repository.setAttributes(attributes); - assertEquals(repository.getAttributes(), attributes); - } - - @Test - public void testKeyedRepository() { - // an object repository of employees who are managers - ObjectRepository managerRepo = db.getRepository(Employee.class, "managers"); - - // an object repository of all employee - ObjectRepository employeeRepo = db.getRepository(Employee.class); - - // and object repository of employees who are developers - ObjectRepository developerRepo = db.getRepository(Employee.class, "developers"); - - Employee manager = new Employee(); - manager.setEmpId(1L); - manager.setAddress("abcd"); - manager.setJoinDate(new Date()); - - Employee developer = new Employee(); - developer.setEmpId(2L); - developer.setAddress("xyz"); - developer.setJoinDate(new Date()); - - managerRepo.insert(manager); - employeeRepo.insert(manager, developer); - developerRepo.insert(developer); - - assertTrue(db.hasRepository(Employee.class)); - assertTrue(db.hasRepository(Employee.class, "managers")); - assertTrue(db.hasRepository(Employee.class, "developers")); - - assertEquals(db.listRepositories().size(), 1); - assertEquals(db.listKeyedRepository().size(), 2); - - assertEquals(employeeRepo.find(where("address").eq("abcd")).size(), 1); - assertEquals(employeeRepo.find(where("address").eq("xyz")).size(), 1); - assertEquals(managerRepo.find(where("address").eq("xyz")).size(), 0); - assertEquals(managerRepo.find(where("address").eq("abcd")).size(), 1); - assertEquals(developerRepo.find(where("address").eq("xyz")).size(), 1); - assertEquals(developerRepo.find(where("address").eq("abcd")).size(), 0); - } - - @Test - public void testEntityRepository() { - ObjectRepository managerRepo = db.getRepository(EmployeeEntity.class, "managers"); - ObjectRepository employeeRepo = db.getRepository(EmployeeEntity.class); - ObjectRepository developerRepo = db.getRepository(EmployeeEntity.class, "developers"); - - managerRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); - employeeRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); - developerRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); - - boolean errored = false; - try { - NitriteCollection collection = db.getCollection("entity.employee"); - } catch (ValidationException e) { - errored = true; - } - assertTrue(errored); - - assertTrue(db.listRepositories().contains("entity.employee")); - assertEquals(db.listKeyedRepository().size(), 2); - assertEquals(db.listCollectionNames().size(), 0); - - assertTrue(managerRepo.hasIndex("firstName")); - assertTrue(managerRepo.hasIndex("lastName")); - assertTrue(employeeRepo.hasIndex("lastName")); - assertTrue(employeeRepo.hasIndex("lastName")); - - managerRepo.drop(); - assertEquals(db.listKeyedRepository().size(), 1); - } - - @Test - public void testIssue217() { - ObjectRepository employeeRepo = db.getRepository(EmployeeEntity.class); - AtomicInteger counter = new AtomicInteger(0); - employeeRepo.subscribe(eventInfo -> counter.incrementAndGet()); - - ObjectRepository employeeRepo2 = db.getRepository(EmployeeEntity.class); - employeeRepo2.insert(new EmployeeEntity()); - await().atMost(5, TimeUnit.SECONDS).until(() -> counter.get() == 1); - } - - @Data - @Entity(value = "entity.employee", indices = { - @Index(value = "firstName", type = IndexType.NonUnique), - @Index(value = "lastName", type = IndexType.NonUnique), - }) - private static class EmployeeEntity implements Mappable { - private static final Faker faker = new Faker(); - - @Id - private Long id; - private String firstName; - private String lastName; - - public EmployeeEntity() { - id = faker.number().randomNumber(); - firstName = faker.name().firstName(); - lastName = faker.name().lastName(); - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("id", id) - .put("firstName", firstName) - .put("lastName", lastName); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Long.class); - firstName = document.get("firstName", String.class); - lastName = document.get("lastName", String.class); - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/ProjectionTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/ProjectionTest.java deleted file mode 100644 index 4e2b9dcd4..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/ProjectionTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository; - -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.rocksdb.repository.data.SubEmployee; -import org.junit.Test; - -import java.util.Iterator; - -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -public class ProjectionTest extends BaseObjectRepositoryTest { - - @Test - public void testHasMore() { - RecordStream iterable = employeeRepository.find().skipLimit(0, 5) - .project(SubEmployee.class); - assertFalse(iterable.isEmpty()); - } - - @Test - public void testSize() { - RecordStream iterable = employeeRepository.find().skipLimit(0, 5) - .project(SubEmployee.class); - assertEquals(iterable.size(), 5); - } - - @Test - public void testToString() { - RecordStream iterable = employeeRepository.find().skipLimit(0, 5) - .project(SubEmployee.class); - assertNotNull(iterable.toString()); - } - - @Test(expected = InvalidOperationException.class) - public void testRemove() { - RecordStream iterable = employeeRepository.find().skipLimit(0, 5) - .project(SubEmployee.class); - Iterator iterator = iterable.iterator(); - if (iterator.hasNext()) { - iterator.next(); - iterator.remove(); - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/RepositoryFactoryTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/RepositoryFactoryTest.java deleted file mode 100644 index 693884346..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/RepositoryFactoryTest.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.*; -import org.dizitart.no2.collection.events.CollectionEventListener; -import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.common.concurrent.LockService; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexEntry; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.repository.RepositoryFactory; -import org.dizitart.no2.rocksdb.DbTestOperations; -import org.dizitart.no2.rocksdb.Retry; -import org.dizitart.no2.rocksdb.TestUtil; -import org.dizitart.no2.store.NitriteStore; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.util.Collection; - -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee - */ -public class RepositoryFactoryTest { - private Nitrite db; - private final String fileName = DbTestOperations.getRandomTempDbFile(); - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testRepositoryFactory() { - RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); - assertNotNull(factory); - } - - @Test(expected = ValidationException.class) - public void testNullType() { - RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); - db = TestUtil.createDb(fileName); - factory.getRepository(db.getConfig(), null, "dummy"); - } - - @Test - public void testNullCollection() { - RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); - db = TestUtil.createDb(fileName); - factory.getRepository(db.getConfig(), DummyCollection.class, null); - } - - @Test(expected = ValidationException.class) - public void testNullContext() { - RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); - factory.getRepository(null, DummyCollection.class, "dummy"); - } - - @After - public void cleanUp() throws IOException { - if (db != null && !db.isClosed()) { - db.close(); - } - TestUtil.deleteFile(fileName); - } - - private static class DummyCollection implements NitriteCollection { - - @Override - public WriteResult update(Filter filter, Document update, UpdateOptions updateOptions) { - return null; - } - - @Override - public WriteResult remove(Filter filter, boolean justOne) { - return null; - } - - @Override - public DocumentCursor find() { - return null; - } - - @Override - public DocumentCursor find(Filter filter) { - return null; - } - - @Override - public Document getById(NitriteId nitriteId) { - return null; - } - - @Override - public String getName() { - return null; - } - - @Override - public void createIndex(String field, IndexOptions indexOptions) { - - } - - @Override - public void rebuildIndex(String field, boolean isAsync) { - - } - - @Override - public Collection listIndices() { - return null; - } - - @Override - public boolean hasIndex(String field) { - return false; - } - - @Override - public boolean isIndexing(String field) { - return false; - } - - @Override - public void dropIndex(String field) { - - } - - @Override - public void dropAllIndices() { - - } - - @Override - public WriteResult insert(Document[] elements) { - return null; - } - - @Override - public WriteResult update(Document element, boolean insertIfAbsent) { - return null; - } - - @Override - public WriteResult remove(Document element) { - return null; - } - - @Override - public void clear() { - - } - - @Override - public void drop() { - - } - - @Override - public boolean isDropped() { - return false; - } - - @Override - public boolean isOpen() { - return false; - } - - @Override - public void close() { - - } - - @Override - public long size() { - return 0; - } - - @Override - public NitriteStore getStore() { - return null; - } - - @Override - public void subscribe(CollectionEventListener listener) { - - } - - @Override - public void unsubscribe(CollectionEventListener listener) { - - } - - @Override - public Attributes getAttributes() { - return null; - } - - @Override - public void setAttributes(Attributes attributes) { - - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/RepositoryJoinTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/RepositoryJoinTest.java deleted file mode 100644 index a21a23442..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/RepositoryJoinTest.java +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.Lookup; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Id; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -public class RepositoryJoinTest extends BaseObjectRepositoryTest { - private ObjectRepository personRepository; - private ObjectRepository
addressRepository; - - @Before - public void setUp() { - openDb(); - - personRepository = db.getRepository(Person.class); - addressRepository = db.getRepository(Address.class); - - for (int i = 0; i < 10; i++) { - Person person = new Person(); - person.setId(Integer.toString(i)); - person.setName("Person " + i); - personRepository.insert(person); - - Address address = new Address(); - address.setPersonId(Integer.toString(i)); - address.setStreet("Street address " + i); - addressRepository.insert(address); - - if (i == 5) { - Address address2 = new Address(); - address2.setPersonId(Integer.toString(i)); - address2.setStreet("Street address 2nd " + i); - addressRepository.insert(address2); - } - } - } - - @After - public void clear() throws IOException { - if (personRepository != null && !personRepository.isDropped()) { - personRepository.remove(ALL); - } - - if (addressRepository != null && !addressRepository.isDropped()) { - addressRepository.remove(ALL); - } - - if (db != null) { - db.commit(); - db.close(); - } - - super.clear(); - } - - @Test - public void testJoin() { - Lookup lookup = new Lookup(); - lookup.setLocalField("id"); - lookup.setForeignField("personId"); - lookup.setTargetField("addresses"); - - RecordStream result - = personRepository.find().join(addressRepository.find(), lookup, - PersonDetails.class); - assertEquals(result.size(), 10); - - for (PersonDetails personDetails : result) { - Address[] addresses = personDetails.addresses.toArray(new Address[0]); - if (personDetails.id.equals("5")) { - assertEquals(addresses.length, 2); - } else { - assertEquals(addresses.length, 1); - assertEquals(addresses[0].personId, personDetails.getId()); - } - } - - result = personRepository.find().skipLimit(0, 5).join(addressRepository.find(), lookup, - PersonDetails.class); - - assertEquals(result.size(), 5); - assertFalse(result.isEmpty()); - assertNotNull(result.toString()); - } - - @Test(expected = InvalidOperationException.class) - public void testRemove() { - Lookup lookup = new Lookup(); - lookup.setLocalField("id"); - lookup.setForeignField("personId"); - lookup.setTargetField("addresses"); - - RecordStream result - = personRepository.find().join(addressRepository.find(), lookup, - PersonDetails.class); - assertEquals(result.size(), 10); - - Iterator iterator = result.iterator(); - if (iterator.hasNext()) { - iterator.next(); - iterator.remove(); - } - } - - @Data - public static class Person implements Mappable { - @Id - private NitriteId nitriteId; - private String id; - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("nitriteId", nitriteId) - .put("id", id) - .put("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - nitriteId = document.get("nitriteId", NitriteId.class); - id = document.get("id", String.class); - name = document.get("name", String.class); - } - } - - @Data - public static class Address implements Mappable { - @Id - private NitriteId nitriteId; - private String personId; - private String street; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("nitriteId", nitriteId) - .put("personId", personId) - .put("street", street); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - nitriteId = document.get("nitriteId", NitriteId.class); - personId = document.get("personId", String.class); - street = document.get("street", String.class); - } - } - - @Data - public static class PersonDetails implements Mappable { - @Id - private NitriteId nitriteId; - private String id; - private String name; - private List
addresses; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("nitriteId", nitriteId) - .put("personId", id) - .put("street", name) - .put("addresses", addresses); - } - - @Override - @SuppressWarnings("unchecked") - public void read(NitriteMapper mapper, Document document) { - nitriteId = document.get("nitriteId", NitriteId.class); - id = document.get("id", String.class); - name = document.get("name", String.class); - Set documents = document.get("addresses", Set.class); - this.addresses = new ArrayList<>(); - for (Document doc : documents) { - Address address = new Address(); - address.read(mapper, doc); - addresses.add(address); - } - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/RepositoryModificationTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/RepositoryModificationTest.java deleted file mode 100644 index 53b047a44..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/RepositoryModificationTest.java +++ /dev/null @@ -1,633 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.InvalidIdException; -import org.dizitart.no2.exceptions.UniqueConstraintException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexEntry; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.rocksdb.repository.data.*; -import org.dizitart.no2.repository.Cursor; -import org.dizitart.no2.repository.ObjectRepository; -import org.junit.Test; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Collection; -import java.util.Date; -import java.util.Locale; - -import static org.awaitility.Awaitility.await; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.*; - - -/** - * @author Anindya Chatterjee. - */ -public class RepositoryModificationTest extends BaseObjectRepositoryTest { - - @Test - public void testCreateIndex() { - assertTrue(companyRepository.hasIndex("companyName")); - assertFalse(companyRepository.hasIndex("dateCreated")); - - companyRepository.createIndex("dateCreated", IndexOptions.indexOptions(IndexType.NonUnique)); - assertTrue(companyRepository.hasIndex("dateCreated")); - assertFalse(companyRepository.isIndexing("dateCreated")); - } - - @Test - public void testRebuildIndex() { - companyRepository.createIndex("dateCreated", IndexOptions.indexOptions(IndexType.NonUnique)); - assertFalse(companyRepository.isIndexing("dateCreated")); - - companyRepository.rebuildIndex("dateCreated", true); - assertTrue(companyRepository.isIndexing("dateCreated")); - - await().until(() -> !companyRepository.isIndexing("dateCreated")); - } - - @Test - public void testListIndexes() { - Collection indices = companyRepository.listIndices(); - assertEquals(indices.size(), 2); - - companyRepository.createIndex("dateCreated", IndexOptions.indexOptions(IndexType.NonUnique)); - indices = companyRepository.listIndices(); - assertEquals(indices.size(), 3); - } - - @Test - public void testDropIndex() { - testListIndexes(); - companyRepository.dropIndex("dateCreated"); - Collection indices = companyRepository.listIndices(); - assertEquals(indices.size(), 2); - } - - @Test - public void testDropAllIndex() { - testListIndexes(); - companyRepository.dropAllIndices(); - Collection indices = companyRepository.listIndices(); - assertEquals(indices.size(), 0); - } - - @Test - public void testCompanyRecord() { - Cursor cursor = companyRepository.find(); - assertEquals(cursor.size(), 10); - assertFalse(cursor.isEmpty()); - } - - @Test - public void testInsert() { - Company company = DataGenerator.generateCompanyRecord(); - Cursor cursor = companyRepository.find(); - assertEquals(cursor.size(), 10); - - companyRepository.insert(company); - cursor = companyRepository.find(); - assertEquals(cursor.size(), 11); - - Company company1 = DataGenerator.generateCompanyRecord(); - Company company2 = DataGenerator.generateCompanyRecord(); - companyRepository.insert(new Company[]{company1, company2}); - cursor = companyRepository.find(); - assertEquals(cursor.size(), 13); - } - - @Test - public void testUpdateWithFilter() { - employeeRepository.remove(Filter.ALL); - - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("abcd road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(new Date()); - Note empNote = new Note(); - empNote.setNoteId(23L); - empNote.setText("sample text note"); - employee.setEmployeeNote(empNote); - - employeeRepository.insert(employee); - Cursor result = employeeRepository.find(); - assertEquals(result.size(), 1); - for (Employee e : result) { - assertEquals(e.getAddress(), "abcd road"); - } - - Employee updated = new Employee(employee); - updated.setAddress("xyz road"); - WriteResult writeResult = employeeRepository.update(where("empId").eq(12L), updated); - assertEquals(writeResult.getAffectedCount(), 1); - result = employeeRepository.find(); - assertEquals(result.size(), 1); - for (Employee e : result) { - assertEquals(e.getAddress(), "xyz road"); - } - } - - @Test - public void testUpdateWithJustOnceFalse() throws ParseException { - Date joiningDate = new Date(); - prepareUpdateWithOptions(joiningDate); - - SimpleDateFormat simpleDateFormat - = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); - Date newJoiningDate = simpleDateFormat.parse("2012-07-01T16:02:48.440Z"); - - Document updated1 = createDocument(); - updated1.put("joinDate", newJoiningDate); - - WriteResult writeResult - = employeeRepository.update(where("empId").eq(12L), updated1, false); - assertEquals(writeResult.getAffectedCount(), 1); - - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 1); - result = employeeRepository.find(where("joinDate").eq(newJoiningDate)); - assertEquals(result.size(), 1); - - employeeRepository.remove(Filter.ALL); - prepareUpdateWithOptions(joiningDate); - result = employeeRepository.find(); - assertEquals(result.size(), 2); - - Document update = createDocument(); - update.put("joinDate", newJoiningDate); - - writeResult = employeeRepository.update(where("joinDate").eq(joiningDate), update, false); - assertEquals(writeResult.getAffectedCount(), 2); - - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - - result = employeeRepository.find(where("joinDate").eq(newJoiningDate)); - assertEquals(result.size(), 2); - } - - @Test - public void testUpsertTrue() { - Date joiningDate = new Date(); - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("some road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(joiningDate); - Note empNote1 = new Note(); - empNote1.setNoteId(23L); - empNote1.setText("sample text note"); - employee.setEmployeeNote(empNote1); - - WriteResult writeResult - = employeeRepository.update(where("empId").eq(12), employee, true); - assertEquals(writeResult.getAffectedCount(), 1); - - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 1); - } - - @Test - public void testUpsertFalse() { - Date joiningDate = new Date(); - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("some road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(joiningDate); - Note empNote1 = new Note(); - empNote1.setNoteId(23L); - empNote1.setText("sample text note"); - employee.setEmployeeNote(empNote1); - - WriteResult writeResult - = employeeRepository.update(where("empId").eq(12), employee, false); - assertEquals(writeResult.getAffectedCount(), 0); - - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - } - - @Test - public void testDeleteFilterAndWithOutOption() { - Date joiningDate = new Date(); - prepareUpdateWithOptions(joiningDate); - - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 2); - - WriteResult writeResult = employeeRepository.remove(where("joinDate").eq(joiningDate)); - assertEquals(writeResult.getAffectedCount(), 2); - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - } - - @Test - public void testDeleteFilterAndWithOption() { - Date joiningDate = new Date(); - prepareUpdateWithOptions(joiningDate); - - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 2); - - WriteResult writeResult = employeeRepository.remove(where("joinDate").eq(joiningDate), true); - assertEquals(writeResult.getAffectedCount(), 1); - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 1); - } - - @Test - public void testEmployeeRecord() { - Iterable totalResult = employeeRepository.find(); - int occurrence = 0; - for (Employee employee : totalResult) { - if (employee.getEmployeeNote().getText().toLowerCase().contains("class aptent")) { - occurrence++; - } - } - - Cursor cursor = employeeRepository.find(where("employeeNote.text").text("Class aptent")); - assertEquals(cursor.size(), occurrence); - } - - @Test - public void testUpdateWithOptions() { - Employee employee = employeeRepository.find().firstOrNull(); - - Document update = createDocument(); - update.put("address", "new address"); - - WriteResult writeResult - = employeeRepository.update(where("empId").eq(employee.getEmpId()), update, false); - assertEquals(writeResult.getAffectedCount(), 1); - - Employee byId = employeeRepository.getById(employee.getEmpId()); - assertEquals(byId.getAddress(), "new address"); - assertEquals(byId.getEmpId(), employee.getEmpId()); - - update.put("address", "another address"); - employeeRepository.update(where("empId").eq(employee.getEmpId()), update); - - byId = employeeRepository.getById(employee.getEmpId()); - assertEquals(byId.getAddress(), "another address"); - assertEquals(byId.getEmpId(), employee.getEmpId()); - } - - @Test(expected = InvalidIdException.class) - public void testMultiUpdateWithObject() { - employeeRepository.remove(Filter.ALL); - - Date now = new Date(); - Employee employee1 = new Employee(); - employee1.setEmpId(1L); - employee1.setAddress("abcd"); - employee1.setJoinDate(now); - - Employee employee2 = new Employee(); - employee2.setEmpId(2L); - employee2.setAddress("xyz"); - employee2.setJoinDate(now); - employeeRepository.insert(employee1, employee2); - - Employee update = new Employee(); - update.setAddress("new address"); - - WriteResult writeResult - = employeeRepository.update(where("joinDate").eq(now), update, false); - assertEquals(writeResult.getAffectedCount(), 0); - } - - @Test - public void testUpdateNull() { - Employee employee = employeeRepository.find().firstOrNull(); - Employee newEmployee = new Employee(employee); - newEmployee.setJoinDate(null); - - Employee result = employeeRepository.find(where("empId").eq(employee.getEmpId())).firstOrNull(); - assertNotNull(result.getJoinDate()); - - WriteResult writeResult = employeeRepository.update(newEmployee, false); - assertEquals(writeResult.getAffectedCount(), 1); - - result = employeeRepository.find(where("empId").eq(employee.getEmpId())).firstOrNull(); - assertNull(result.getJoinDate()); - - // update with object filter and item and set id different - } - - @Test - public void testUpdateWithChangedId() { - Employee employee = employeeRepository.find().firstOrNull(); - Long oldId = employee.getEmpId(); - long count = employeeRepository.size(); - - Employee newEmployee = new Employee(employee); - newEmployee.setEmpId(50L); - - Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); - assertNotNull(result.getJoinDate()); - - WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); - assertEquals(writeResult.getAffectedCount(), 1); - - assertEquals(count, employeeRepository.size()); - Cursor cursor = employeeRepository.find(where("empId").eq(oldId)); - assertEquals(cursor.size(), 0); - } - - @Test(expected = InvalidIdException.class) - public void testUpdateWithNullId() { - Employee employee = employeeRepository.find().firstOrNull(); - Long oldId = employee.getEmpId(); - - Employee newEmployee = new Employee(employee); - newEmployee.setEmpId(null); - - Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); - assertNotNull(result.getJoinDate()); - - WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); - assertEquals(writeResult.getAffectedCount(), 1); - } - - @Test(expected = UniqueConstraintException.class) - public void testUpdateWithDuplicateId() { - Employee employee = employeeRepository.find().firstOrNull(); - Long oldId = employee.getEmpId(); - long count = employeeRepository.size(); - - Employee newEmployee = new Employee(employee); - newEmployee.setEmpId(5L); - - Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); - assertNotNull(result.getJoinDate()); - - WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); - assertEquals(writeResult.getAffectedCount(), 1); - - assertEquals(count, employeeRepository.size()); - Cursor cursor = employeeRepository.find(where("empId").eq(oldId)); - assertEquals(cursor.size(), 0); - } - - @Test - public void testUpdateWithObject() { - Employee employee = employeeRepository.find().firstOrNull(); - Employee newEmployee = new Employee(employee); - - Long id = employee.getEmpId(); - String address = employee.getAddress(); - newEmployee.setAddress("new address"); - - WriteResult writeResult = employeeRepository.update(newEmployee); - assertEquals(writeResult.getAffectedCount(), 1); - - Employee emp = employeeRepository.find(where("empId").eq(id)).firstOrNull(); - assertNotEquals(address, emp.getAddress()); - assertEquals(employee.getEmpId(), emp.getEmpId()); - assertEquals(employee.getJoinDate(), emp.getJoinDate()); - assertArrayEquals(employee.getBlob(), emp.getBlob()); - } - - @Test - public void testUpsertWithObject() { - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("some road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(new Date()); - Note empNote = new Note(); - empNote.setNoteId(23L); - empNote.setText("sample text note"); - employee.setEmployeeNote(empNote); - - WriteResult writeResult = employeeRepository.update(employee, false); - assertEquals(writeResult.getAffectedCount(), 0); - writeResult = employeeRepository.update(employee, true); - assertEquals(writeResult.getAffectedCount(), 1); - - Employee emp = employeeRepository.find(where("empId").eq(12L)).firstOrNull(); - assertEquals(emp, employee); - } - - @Test - public void testRemoveObject() { - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("some road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(new Date()); - Note empNote = new Note(); - empNote.setNoteId(23L); - empNote.setText("sample text note"); - employee.setEmployeeNote(empNote); - - long size = employeeRepository.size(); - - employeeRepository.insert(employee); - assertEquals(employeeRepository.size(), size + 1); - - employeeRepository.remove(employee); - assertEquals(employeeRepository.size(), size); - - Employee emp = employeeRepository.find(where("empId").eq(12L)).firstOrNull(); - assertNull(emp); - } - - private void prepareUpdateWithOptions(Date joiningDate) { - employeeRepository.remove(Filter.ALL); - - Employee employee1 = new Employee(); - employee1.setCompany(null); - employee1.setAddress("some road"); - employee1.setBlob(new byte[]{1, 2, 125}); - employee1.setEmpId(12L); - employee1.setJoinDate(joiningDate); - Note empNote1 = new Note(); - empNote1.setNoteId(23L); - empNote1.setText("sample text note"); - employee1.setEmployeeNote(empNote1); - - Employee employee2 = new Employee(); - employee2.setCompany(null); - employee2.setAddress("other road"); - employee2.setBlob(new byte[]{10, 12, 25}); - employee2.setEmpId(2L); - employee2.setJoinDate(joiningDate); - Note empNote2 = new Note(); - empNote2.setNoteId(2L); - empNote2.setText("some random note"); - employee2.setEmployeeNote(empNote2); - - employeeRepository.insert(employee1, employee2); - Cursor result = employeeRepository.find(); - assertEquals(result.size(), 2); - for (Employee e : result.project(Employee.class)) { - assertEquals(e.getJoinDate(), joiningDate); - } - } - - @Test - public void testUpdateWithDoc() { - Note note = new Note(); - note.setNoteId(10L); - note.setText("some note text"); - - Document document = createDocument("address", "some address") - .put("employeeNote", note); - - WriteResult result = employeeRepository.update(Filter.ALL, document); - assertEquals(result.getAffectedCount(), 10); - } - - @Test - public void testDeleteIteratorNPE() { - ObjectRepository notes = db.getRepository(Note.class); - Note one = new Note(); - one.setText("Jane"); - one.setNoteId(1L); - Note two = new Note(); - two.setText("Jill"); - two.setNoteId(2L); - - notes.insert(one, two); - - WriteResult writeResult = notes.remove(where("text").eq("Pete")); - for (NitriteId id : writeResult) { - assertNotNull(id); - } - } - - @Test - public void testDelete() { - ObjectRepository repo = db.getRepository(WithNitriteId.class); - WithNitriteId one = new WithNitriteId(); - one.setName("Jane"); - repo.insert(one); - - WithNitriteId note = repo.find().firstOrNull(); - repo.remove(note); - - assertNull(repo.getById(one.idField)); - } - - /* - * Upsert Use Cases - * - * 1. Object does not exists - * a. if upsert true, it will insert - * b. if upsert false, nothing happens - * 2. Object exists - * a. if upsert true, it will update, old id remains same - * b. if upsert false, it will update, old id remains same - * - * */ - - @Test - public void testUpdateObjectNotExistsUpsertTrue() { - ObjectRepository repo = db.getRepository(InternalClass.class); - InternalClass a = new InternalClass(); - a.setId(1); - a.setName("first"); - repo.insert(a); - - a = new InternalClass(); - a.setId(2); - a.setName("second"); - - // it will insert as new object - repo.update(a, true); - assertEquals(repo.size(), 2); - } - - @Test - public void testUpdateObjectNotExistsUpsertFalse() { - ObjectRepository repo = db.getRepository(InternalClass.class); - InternalClass a = new InternalClass(); - a.setId(1); - a.setName("first"); - repo.insert(a); - - a = new InternalClass(); - a.setId(2); - a.setName("second"); - - // no changes will happen to repository - repo.update(a, false); - assertEquals(repo.size(), 1); - assertEquals(repo.find().firstOrNull().getId(), 1); - assertEquals(repo.find().firstOrNull().getName(), "first"); - } - - @Test - public void testUpdateObjectExistsUpsertTrue() { - ObjectRepository repo = db.getRepository(InternalClass.class); - InternalClass a = new InternalClass(); - a.setId(1); - a.setName("first"); - repo.insert(a); - - a = new InternalClass(); - a.setId(1); - a.setName("second"); - - // update existing object, keep id same - repo.update(a, true); - assertEquals(repo.size(), 1); - assertEquals(repo.find().firstOrNull().getId(), 1); - assertEquals(repo.find().firstOrNull().getName(), "second"); - } - - @Test - public void testUpdateObjectExistsUpsertFalse() { - ObjectRepository repo = db.getRepository(InternalClass.class); - InternalClass a = new InternalClass(); - a.setId(1); - a.setName("first"); - repo.insert(a); - - a = new InternalClass(); - a.setId(1); - a.setName("second"); - - // update existing object, keep id same - repo.update(a, false); - assertEquals(repo.size(), 1); - assertEquals(repo.find().firstOrNull().getId(), 1); - assertEquals(repo.find().firstOrNull().getName(), "second"); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/RepositorySearchTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/RepositorySearchTest.java deleted file mode 100644 index 9181c502e..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/RepositorySearchTest.java +++ /dev/null @@ -1,608 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository; - -import lombok.Getter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.exceptions.InvalidIdException; -import org.dizitart.no2.exceptions.NotIdentifiableException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.rocksdb.repository.data.*; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.Cursor; -import org.dizitart.no2.repository.ObjectRepository; -import org.junit.Test; - -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.List; - -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.$; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class RepositorySearchTest extends BaseObjectRepositoryTest { - @Test - public void testFindWithOptions() { - Cursor cursor = employeeRepository.find().skipLimit(0, 1); - assertEquals(cursor.size(), 1); - assertNotNull(cursor.firstOrNull()); - } - - @Test - public void testEmployeeProjection() { - List employeeList = employeeRepository.find().toList(); - List subEmployeeList - = employeeRepository.find().project(SubEmployee.class).toList(); - - assertNotNull(employeeList); - assertNotNull(subEmployeeList); - - assertTrue(employeeList.size() > 0); - assertTrue(subEmployeeList.size() > 0); - - assertEquals(employeeList.size(), subEmployeeList.size()); - - for (int i = 0; i < subEmployeeList.size(); i++) { - Employee employee = employeeList.get(i); - SubEmployee subEmployee = subEmployeeList.get(i); - - assertEquals(employee.getEmpId(), subEmployee.getEmpId()); - assertEquals(employee.getJoinDate(), subEmployee.getJoinDate()); - assertEquals(employee.getAddress(), subEmployee.getAddress()); - } - - Cursor cursor = employeeRepository.find(); - assertNotNull(cursor.firstOrNull()); - assertNotNull(cursor.toString()); - assertEquals(cursor.toList().size(), employeeList.size()); - assertNotNull(cursor.firstOrNull()); - assertEquals(cursor.toList().size(), employeeList.size()); - } - - @Test - public void testEmptyResultProjection() { - employeeRepository.remove(ALL); - assertNull(employeeRepository.find().firstOrNull()); - - assertNull(employeeRepository.find(where("empId").eq(-1)) - .firstOrNull()); - } - - @Test - public void testGetById() { - ObjectRepository empRepo = db.getRepository(Employee.class); - Employee e1 = DataGenerator.generateEmployee(); - Employee e2 = DataGenerator.generateEmployee(); - Employee e3 = DataGenerator.generateEmployee(); - Employee e4 = DataGenerator.generateEmployee(); - - e1.setEmpId(1000000L); - e2.setEmpId(2000000L); - e3.setEmpId(3000000L); - e4.setEmpId(4000000L); - - empRepo.insert(e1, e2, e3, e4); - - Employee byId = empRepo.getById(2000000L); - assertEquals(byId, e2); - } - - @Test(expected = NotIdentifiableException.class) - public void testGetByIdNoId() { - ObjectRepository repository = db.getRepository(Note.class); - Note n1 = DataGenerator.randomNote(); - Note n2 = DataGenerator.randomNote(); - Note n3 = DataGenerator.randomNote(); - - assert n1 != null; - n1.setNoteId(1000000L); - assert n2 != null; - n2.setNoteId(2000000L); - assert n3 != null; - n3.setNoteId(3000000L); - - repository.insert(n1, n2, n3); - - repository.getById(2000000L); - } - - @Test(expected = InvalidIdException.class) - public void testGetByIdNullId() { - ObjectRepository empRepo = db.getRepository(Employee.class); - Employee e1 = DataGenerator.generateEmployee(); - Employee e2 = DataGenerator.generateEmployee(); - Employee e3 = DataGenerator.generateEmployee(); - Employee e4 = DataGenerator.generateEmployee(); - - e1.setEmpId(1000000L); - e2.setEmpId(2000000L); - e3.setEmpId(3000000L); - e4.setEmpId(4000000L); - - empRepo.insert(e1, e2, e3, e4); - - empRepo.getById(null); - } - - @Test(expected = InvalidIdException.class) - public void testGetByIdWrongType() { - ObjectRepository empRepo = db.getRepository(Employee.class); - Employee e1 = DataGenerator.generateEmployee(); - Employee e2 = DataGenerator.generateEmployee(); - Employee e3 = DataGenerator.generateEmployee(); - Employee e4 = DataGenerator.generateEmployee(); - - e1.setEmpId(1000000L); - e2.setEmpId(2000000L); - e3.setEmpId(3000000L); - e4.setEmpId(4000000L); - - empRepo.insert(e1, e2, e3, e4); - - Employee byId = empRepo.getById("employee"); - assertNull(byId); - } - - @Test - public void testEqualFilterById() { - Employee employee = employeeRepository.find().firstOrNull(); - long empId = employee.getEmpId(); - Employee emp = employeeRepository.find(where("empId").eq(empId)) - .project(Employee.class).firstOrNull(); - assertEquals(employee, emp); - } - - @Test - public void testEqualFilter() { - Employee employee = employeeRepository.find() - .firstOrNull(); - - Employee emp = employeeRepository.find(where("joinDate").eq(employee.getJoinDate())) - .project(Employee.class) - .firstOrNull(); - assertEquals(employee, emp); - } - - @Test - public void testStringEqualFilter() { - ObjectRepository repository = db.getRepository(ProductScore.class); - - ProductScore object = new ProductScore(); - object.setProduct("test"); - object.setScore(1); - repository.insert(object); - - object = new ProductScore(); - object.setProduct("test"); - object.setScore(2); - repository.insert(object); - - object = new ProductScore(); - object.setProduct("another-test"); - object.setScore(3); - repository.insert(object); - - assertEquals(repository.find(where("product").eq("test")).size(), 2); - } - - @Test - public void testAndFilter() { - Employee emp = employeeRepository.find().firstOrNull(); - - long id = emp.getEmpId(); - String address = emp.getAddress(); - Date joinDate = emp.getJoinDate(); - - Employee employee = employeeRepository.find( - where("empId").eq(id) - .and( - where("address").regex(address) - .and( - where("joinDate").eq(joinDate)))).firstOrNull(); - - assertEquals(emp, employee); - } - - @Test - public void testOrFilter() { - Employee emp = employeeRepository.find().firstOrNull(); - long id = emp.getEmpId(); - - Employee employee = employeeRepository.find( - where("empId").eq(id) - .or( - where("address").regex("n/a") - .or( - where("joinDate").eq(null)))).firstOrNull(); - - assertEquals(emp, employee); - } - - @Test - public void testNotFilter() { - Employee emp = employeeRepository.find().firstOrNull(); - long id = emp.getEmpId(); - - Employee employee = employeeRepository.find( - where("empId").eq(id).not()).firstOrNull(); - assertNotEquals(emp, employee); - } - - @Test - public void testGreaterFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Ascending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").gt(id)) - .toList(); - - assertFalse(employeeList.contains(emp)); - assertEquals(employeeList.size(), 9); - } - - @Test - public void testGreaterEqualFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Ascending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").gte(id)) - .toList(); - - assertTrue(employeeList.contains(emp)); - assertEquals(employeeList.size(), 10); - } - - @Test - public void testLesserThanFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Descending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").lt(id)) - .toList(); - - assertFalse(employeeList.contains(emp)); - assertEquals(employeeList.size(), 9); - } - - @Test - public void testLesserEqualFilter() { - employeeRepository = db.getRepository(Employee.class); - - Employee emp = employeeRepository.find().sort("empId", SortOrder.Descending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").lte(id)) - .toList(); - - assertTrue(employeeList.contains(emp)); - assertEquals(employeeList.size(), 10); - } - - @Test - public void testTextFilter() { - Employee emp = employeeRepository.find().firstOrNull(); - String text = emp.getEmployeeNote().getText(); - - List employeeList = employeeRepository.find(where("employeeNote.text").text(text)) - .toList(); - - assertTrue(employeeList.contains(emp)); - } - - @Test - public void testRegexFilter() { - RecordStream employees = employeeRepository.find(); - int count = employees.toList().size(); - - List employeeList = employeeRepository.find(where("employeeNote.text").regex(".*")) - .toList(); - - assertEquals(employeeList.size(), count); - } - - @Test - public void testInFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Descending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").in(id, id - 1, id - 2)) - .toList(); - - assertTrue(employeeList.contains(emp)); - assertEquals(employeeList.size(), 3); - - employeeList = employeeRepository.find(where("empId").in(id - 1, id - 2)).toList(); - assertEquals(employeeList.size(), 2); - } - - @Test - public void testNotInFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Descending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").notIn(id, id - 1, id - 2)) - .toList(); - - assertFalse(employeeList.contains(emp)); - assertEquals(employeeList.size(), 7); - - employeeList = employeeRepository.find(where("empId").notIn(id - 1, id - 2)).toList(); - assertEquals(employeeList.size(), 8); - } - - @Test - public void testElemMatchFilter() { - final ProductScore score1 = new ProductScore("abc", 10); - final ProductScore score2 = new ProductScore("abc", 8); - final ProductScore score3 = new ProductScore("abc", 7); - final ProductScore score4 = new ProductScore("xyz", 5); - final ProductScore score5 = new ProductScore("xyz", 7); - final ProductScore score6 = new ProductScore("xyz", 8); - - ObjectRepository repository = db.getRepository(ElemMatch.class); - ElemMatch e1 = new ElemMatch() {{ - setId(1); - setStrArray(new String[]{"a", "b"}); - setProductScores(new ProductScore[]{score1, score4}); - }}; - ElemMatch e2 = new ElemMatch() {{ - setId(2); - setStrArray(new String[]{"d", "e"}); - setProductScores(new ProductScore[]{score2, score5}); - }}; - ElemMatch e3 = new ElemMatch() {{ - setId(3); - setStrArray(new String[]{"a", "f"}); - setProductScores(new ProductScore[]{score3, score6}); - }}; - - repository.insert(e1, e2, e3); - - List elements = repository.find( - where("productScores").elemMatch( - where("product").eq("xyz") - .and(where("score").gte(8)))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("score").lte(8).not())).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("product").eq("xyz") - .or(where("score").gte(8)))).toList(); - assertEquals(elements.size(), 3); - - elements = repository.find( - where("productScores").elemMatch( - where("product").eq("xyz"))).toList(); - assertEquals(elements.size(), 3); - - elements = repository.find( - where("productScores").elemMatch( - where("score").gte(10))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("score").gt(8))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("score").lt(7))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("score").lte(7))).toList(); - assertEquals(elements.size(), 3); - - elements = repository.find( - where("productScores").elemMatch( - where("score").in(7, 8))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find( - where("productScores").elemMatch( - where("score").notIn(7, 8))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("product").regex("xyz"))).toList(); - assertEquals(elements.size(), 3); - - elements = repository.find(where("strArray").elemMatch($.eq("a"))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find( - where("strArray").elemMatch( - $.eq("a") - .or($.eq("f") - .or($.eq("b"))).not())).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find(where("strArray").elemMatch($.gt("e"))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find(where("strArray").elemMatch($.gte("e"))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find(where("strArray").elemMatch($.lte("b"))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find(where("strArray").elemMatch($.lt("a"))).toList(); - assertEquals(elements.size(), 0); - - elements = repository.find(where("strArray").elemMatch($.in("a", "f"))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find(where("strArray").elemMatch($.regex("a"))).toList(); - assertEquals(elements.size(), 2); - } - - @Test - public void testFilterAll() { - ObjectRepository repository = db.getRepository(ElemMatch.class); - Cursor cursor = repository.find(ALL); - assertNotNull(cursor); - assertEquals(cursor.size(), 0); - - repository.insert(new ElemMatch()); - cursor = repository.find(ALL); - assertNotNull(cursor); - assertEquals(cursor.size(), 1); - } - - @Test - public void testEqualsOnTextIndex() { - PersonEntity p1 = new PersonEntity("jhonny"); - PersonEntity p2 = new PersonEntity("jhonny"); - PersonEntity p3 = new PersonEntity("jhonny"); - - ObjectRepository repository = db.getRepository(PersonEntity.class); - repository.insert(p1); - repository.insert(p2); - repository.insert(p3); - - List sameNamePeople = repository.find(where("name").eq("jhonny")).toList(); - assertEquals(sameNamePeople.size(), 3); - - sameNamePeople = repository.find(where("name").eq("JHONNY")).toList(); - assertEquals(sameNamePeople.size(), 0); - - sameNamePeople = repository.find(where("name").text("jhonny")).toList(); - assertEquals(sameNamePeople.size(), 3); - - sameNamePeople = repository.find(where("name").text("JHONNY")).toList(); - assertEquals(sameNamePeople.size(), 3); - - sameNamePeople = repository.find(where("name").eq("jhon*")).toList(); - assertEquals(sameNamePeople.size(), 0); - - sameNamePeople = repository.find(where("name").text("jhon*")).toList(); - assertEquals(sameNamePeople.size(), 3); - } - - @Test - public void testIssue62() { - PersonEntity p1 = new PersonEntity("abcd"); - p1.setStatus("Married"); - - PersonEntity p2 = new PersonEntity("efgh"); - p2.setStatus("Married"); - - PersonEntity p3 = new PersonEntity("ijkl"); - p3.setStatus("Un-Married"); - - ObjectRepository repository = db.getRepository(PersonEntity.class); - repository.insert(p1); - repository.insert(p2); - repository.insert(p3); - - Filter married = where("status").eq("Married"); - - assertEquals(repository.find(married).size(), 2); - assertEquals(repository.find(married).sort("status", SortOrder.Descending).size(), 2); - - assertEquals(repository.find().sort("status", SortOrder.Descending).firstOrNull().getStatus(), "Un-Married"); - - assertEquals(repository.find().sort("status", SortOrder.Ascending).size(), 3); - assertEquals(repository.find().sort("status", SortOrder.Ascending).firstOrNull().getStatus(), "Married"); - } - - @Test - public void testRepeatableIndexAnnotation() { - ObjectRepository repo = db.getRepository(RepeatableIndexTest.class); - RepeatableIndexTest first = new RepeatableIndexTest(); - first.setAge(12); - first.setFirstName("fName"); - first.setLastName("lName"); - repo.insert(first); - - assertTrue(repo.hasIndex("firstName")); - assertTrue(repo.hasIndex("age")); - assertTrue(repo.hasIndex("lastName")); - - assertEquals(repo.find(where("age").eq(12)).firstOrNull(), first); - } - - @Test - public void testIdSet() { - Cursor employees = employeeRepository.find().sort("empId", SortOrder.Ascending); - assertEquals(employees.size(), 10); - } - - @Test - public void testBetweenFilter() { - @Getter - class TestData implements Mappable { - private Date age; - - public TestData(Date age) { - this.age = age; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("age", age); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - age = document.get("age", Date.class); - } - } - - TestData data1 = new TestData(new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime()); - TestData data2 = new TestData(new GregorianCalendar(2021, Calendar.FEBRUARY, 12).getTime()); - TestData data3 = new TestData(new GregorianCalendar(2022, Calendar.MARCH, 13).getTime()); - TestData data4 = new TestData(new GregorianCalendar(2023, Calendar.APRIL, 14).getTime()); - TestData data5 = new TestData(new GregorianCalendar(2024, Calendar.MAY, 15).getTime()); - TestData data6 = new TestData(new GregorianCalendar(2025, Calendar.JUNE, 16).getTime()); - - ObjectRepository repository = db.getRepository(TestData.class); - repository.insert(data1, data2, data3, data4, data5, data6); - - Cursor cursor = repository.find(where("age").between( - new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), - new GregorianCalendar(2025, Calendar.JUNE, 16).getTime())); - assertEquals(cursor.size(), 6); - - cursor = repository.find(where("age").between( - new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), - new GregorianCalendar(2025, Calendar.JUNE, 16).getTime(), false)); - assertEquals(cursor.size(), 4); - - cursor = repository.find(where("age").between( - new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), - new GregorianCalendar(2025, Calendar.JUNE, 16).getTime(), false, true)); - assertEquals(cursor.size(), 5); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/UnAnnotatedObjectTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/UnAnnotatedObjectTest.java deleted file mode 100644 index e3aab29aa..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/UnAnnotatedObjectTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository; - - -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.rocksdb.repository.data.ClassA; -import org.dizitart.no2.rocksdb.repository.data.ClassC; -import org.dizitart.no2.repository.Cursor; -import org.junit.Test; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -/** - * @author Anindya Chatterjee. - */ -public class UnAnnotatedObjectTest extends BaseObjectRepositoryTest { - - @Test - @SuppressWarnings("unchecked") - public void testFind() { - Cursor cursor = aObjectRepository.find(); - assertEquals(cursor.size(), 10); - assertFalse(cursor.isEmpty()); - - IndexOptions indexOptions = new IndexOptions(); - indexOptions.setIndexType(IndexType.Unique); - aObjectRepository.createIndex("b.number", indexOptions); - - cursor = aObjectRepository.find(where("b.number").eq(160).not()). - sort("b.number", SortOrder.Ascending).skipLimit(0, 10); - - System.out.println("Available - " + !cursor.isEmpty()); - System.out.println("Total Size - " + cursor.size()); - - Iterable findRecord = cursor.project(ClassA.class); - for (ClassA classA : findRecord) { - System.out.println(classA); - } - - cursor = aObjectRepository.find(where("b.number").eq(160).not()). - sort("b.number", SortOrder.Descending).skipLimit(2, 7); - - System.out.println("Available - " + !cursor.isEmpty()); - System.out.println("Total Size - " + cursor.size()); - - findRecord = cursor.project(ClassA.class); - for (ClassA classA : findRecord) { - System.out.println(classA); - } - - cursor = cObjectRepository.find(where("id").gt(900)). - sort("id", SortOrder.Descending).skipLimit(2, 7); - System.out.println("Available - " + !cursor.isEmpty()); - System.out.println("Total Size - " + cursor.size()); - - Iterable findRecordC = cursor.project(ClassC.class); - for (ClassC classC : findRecordC) { - System.out.println(classC); - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/UniversalTextTokenizerTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/UniversalTextTokenizerTest.java deleted file mode 100644 index 0b9c91ae9..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/UniversalTextTokenizerTest.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.index.NitriteTextIndexer; -import org.dizitart.no2.index.fulltext.Languages; -import org.dizitart.no2.index.fulltext.UniversalTextTokenizer; -import org.dizitart.no2.rocksdb.RocksDBModule; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.Cursor; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.IOException; - -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.rocksdb.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.rocksdb.TestUtil.deleteFile; -import static org.dizitart.no2.module.NitriteModule.module; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -/** - * @author Anindya Chatterjee - */ -public class UniversalTextTokenizerTest extends BaseObjectRepositoryTest { - private final String fileName = getRandomTempDbFile(); - private ObjectRepository textRepository; - - @Before - @Override - public void setUp() { - openDb(); - textRepository = db.getRepository(TextData.class); - - for (int i = 0; i < 10; i++) { - TextData data = new TextData(); - data.id = i; - if (i % 2 == 0) { - data.text = "তারা বলল, “এস আমরা আমাদের জন্যে এক বড় শহর বানাই| আর এমন একটি উঁচু স্তম্ভ বানাই " + - "যা আকাশ স্পর্শ করবে| তাহলে আমরা বিখ্যাত হব এবং এটা আমাদের এক সঙ্গে ধরে রাখবে| সারা পৃথিবীতে " + - "আমরা ছড়িয়ে থাকব না|”"; - } else if (i % 3 == 0) { - data.text = "部汁楽示時葉没式将場参右属。覧観将者雄日語山銀玉襲政著約域費。新意虫跡更味株付安署審完顔団。" + - "困更表転定一史賀面政巣迎文学豊税乗。白間接特時京転閉務講封新内。側流効表害場測投活聞秀職探画労。" + - "福川順式極木注美込行警検直性禁遅。土一詳非物質紙姿漢人内池銀周街躍澹二。平討聞述並時全経詳業映回作朝送恵時。"; - } else if (i % 5 == 0) { - data.text = " أقبل لسفن العالم، في أما, بـ بال أملاً الثالث،. الذود بالرّد الثالث، مع" + - " قام, كردة الضغوط الإمداد أن وصل. ٠٨٠٤ عُقر انتباه يكن قد, أن زهاء وفنلندا بال. لان ما يقوم المعاهدات," + - " بـ بخطوط استعملت عدد. صفحة لفشل ولاتّساع لم قام, في مكثّفة الكونجرس جعل, الثالث، واقتصار دون ان.\n"; - } else { - data.text = "Lorem ipsum dolor sit amet, nobis audire perpetua eu sea. Te semper causae " + - "efficiantur per. Qui affert dolorum at. Mel tale constituto interesset in."; - } - textRepository.insert(data); - } - } - - @After - @Override - public void clear() throws IOException { - if (textRepository != null && !textRepository.isDropped()) { - textRepository.remove(ALL); - } - - if (db != null) { - db.commit(); - db.close(); - } - - deleteFile(fileName); - } - - @Override - protected void openDb() { - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(fileName) - .build(); - - NitriteBuilder nitriteBuilder = Nitrite.builder() - .fieldSeparator(".") - .loadModule(storeModule); - - UniversalTextTokenizer tokenizer; - if (isProtected) { - tokenizer = new UniversalTextTokenizer(Languages.Bengali, Languages.Chinese, Languages.English); - } else { - tokenizer = new UniversalTextTokenizer(Languages.ALL); - } - nitriteBuilder.loadModule(module(new NitriteTextIndexer(tokenizer))); - - if (isProtected) { - db = nitriteBuilder.openOrCreate("test-user", "test-password"); - } else { - db = nitriteBuilder.openOrCreate(); - } - } - - @Test - public void testUniversalFullTextIndexing() { - Cursor cursor = textRepository.find(where("text").text("Lorem")); - assertEquals(cursor.size(), 2); - for (TextData data : cursor) { - System.out.println("Id for English text -> " + data.id); - if (data.id % 2 == 0 || data.id % 3 == 0 || data.id % 5 == 0) { - fail(); - } - } - - cursor = textRepository.find(where("text").text("শহর")); - assertEquals(cursor.size(), 5); - for (TextData data : cursor) { - System.out.println("Id for Bengali text -> " + data.id); - if (data.id % 2 != 0) { - fail(); - } - } - - cursor = textRepository.find(where("text").text("転閉")); - assertEquals(cursor.size(), 0); - cursor = textRepository.find(where("text").text("*転閉*")); - assertEquals(cursor.size(), 2); - for (TextData data : cursor) { - System.out.println("Id for Chinese text -> " + data.id); - if (data.id % 3 != 0) { - fail(); - } - } - - cursor = textRepository.find(where("text").text("أقبل")); - if (isProtected) { - assertEquals(cursor.size(), 1); - for (TextData data : cursor) { - System.out.println("Id for Arabic text -> " + data.id); - if (data.id % 5 != 0) { - fail(); - } - } - } else { - // أقبل eliminated as stop word - assertEquals(cursor.size(), 0); - } - } - - @Indices( - @Index(value = "text", type = IndexType.Fulltext) - ) - public static class TextData implements Mappable { - public int id; - public String text; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("id", id) - .put("text", text); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Integer.class); - text = document.get("text", String.class); - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ChildClass.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ChildClass.java deleted file mode 100644 index d6044f010..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ChildClass.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.InheritIndices; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@InheritIndices -public class ChildClass extends ParentClass { - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return super.write(mapper).put("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - super.read(mapper, document); - name = document.get("name", String.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ClassA.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ClassA.java deleted file mode 100644 index bb8fceb6c..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ClassA.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.util.UUID; - -@EqualsAndHashCode -@ToString -public class ClassA implements Mappable { - @Getter - @Setter - private ClassB classB; - @Getter - @Setter - private UUID uid; - @Getter - @Setter - private String string; - @Getter - @Setter - private byte[] blob; - - public static ClassA create(int seed) { - ClassB classB = ClassB.create(seed); - ClassA classA = new ClassA(); - classA.classB = classB; - classA.uid = new UUID(seed, seed + 50); - classA.string = Integer.toHexString(seed); - classA.blob = new byte[]{(byte) seed}; - return classA; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("classB", classB != null ? classB.write(mapper) : null) - .put("uid", uid) - .put("string", string) - .put("blob", blob); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - if (document.get("classB") != null) { - classB = new ClassB(); - classB.read(mapper, document.get("classB", Document.class)); - } - uid = document.get("uid", UUID.class); - string = document.get("string", String.class); - blob = document.get("blob", byte[].class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ClassB.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ClassB.java deleted file mode 100644 index 927827377..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ClassB.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -@EqualsAndHashCode -@ToString -class ClassB implements Comparable, Mappable { - @Getter - @Setter - private int number; - @Getter - @Setter - private String text; - - static ClassB create(int seed) { - ClassB classB = new ClassB(); - classB.setNumber(seed + 100); - classB.setText(Integer.toBinaryString(seed)); - return classB; - } - - @Override - public int compareTo(ClassB o) { - return Integer.compare(number, o.number); - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("number", number) - .put("text", text); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - number = document.get("number", Integer.class); - text = document.get("text", String.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ClassC.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ClassC.java deleted file mode 100644 index 9a93a7d02..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ClassC.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -@EqualsAndHashCode -@ToString -public class ClassC implements Mappable { - @Getter - @Setter - private long id; - @Getter - @Setter - private double digit; - @Getter - @Setter - private ClassA parent; - - public static ClassC create(int seed) { - ClassC classC = new ClassC(); - classC.id = seed * 5000; - classC.digit = seed * 69.65; - classC.parent = ClassA.create(seed); - return classC; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("id", id) - .put("digit", digit) - .put("parent", parent != null ? parent.write(mapper) : null); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Long.class); - digit = document.get("digit", Double.class); - if (document.get("parent") != null) { - parent = new ClassA(); - parent.read(mapper, document.get("parent", Document.class)); - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/Company.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/Company.java deleted file mode 100644 index 53863170e..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/Company.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; - -import java.io.Serializable; -import java.util.Date; -import java.util.List; -import java.util.Map; - -/** - * @author Anindya Chatterjee. - */ -@ToString -@EqualsAndHashCode -@Indices({ - @Index(value = "companyName") -}) -public class Company implements Serializable, Mappable { - @Id - @Getter - @Setter - private Long companyId; - - @Getter - @Setter - private String companyName; - - @Getter - @Setter - private Date dateCreated; - - @Getter - @Setter - private List departments; - - @Getter - @Setter - private Map> employeeRecord; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("companyId", companyId) - .put("companyName", companyName) - .put("dateCreated", dateCreated) - .put("departments", departments) - .put("employeeRecord", employeeRecord); - } - - @Override - @SuppressWarnings("unchecked") - public void read(NitriteMapper mapper, Document document) { - companyId = document.get("companyId", Long.class); - companyName = document.get("companyName", String.class); - dateCreated = document.get("dateCreated", Date.class); - departments = document.get("departments", List.class); - employeeRecord = document.get("employeeRecord", Map.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/DataGenerator.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/DataGenerator.java deleted file mode 100644 index 5d5dbfd81..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/DataGenerator.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @author Anindya Chatterjee. - */ -public class DataGenerator { - private DataGenerator() {} - - private static final Random random = new Random(System.currentTimeMillis()); - private static final AtomicInteger counter = new AtomicInteger(random.nextInt()); - - public static Company generateCompanyRecord() { - Company company = new Company(); - company.setCompanyId(System.nanoTime() + counter.incrementAndGet()); - company.setCompanyName(randomCompanyName()); - company.setDateCreated(randomDate()); - List departments = departments(); - company.setDepartments(departments); - - Map> employeeRecord = new HashMap<>(); - for (String department : departments) { - employeeRecord.put(department, - generateEmployeeRecords(company, random.nextInt(20))); - } - company.setEmployeeRecord(employeeRecord); - return company; - } - - private static List generateEmployeeRecords(Company company, int count) { - List employeeList = new ArrayList<>(); - for (int i = 0; i < count; i++) { - Employee employee = generateEmployee(); - employee.setCompany(company); - employeeList.add(employee); - } - return employeeList; - } - - public static Employee generateEmployee() { - Employee employee = new Employee(); - employee.setEmpId(System.nanoTime() + counter.incrementAndGet()); - employee.setJoinDate(randomDate()); - employee.setAddress(UUID.randomUUID().toString().replace('-', ' ')); - - byte[] blob = new byte[random.nextInt(8000)]; - random.nextBytes(blob); - employee.setBlob(blob); - employee.setEmployeeNote(randomNote()); - - return employee; - } - - private static Date randomDate() { - return new Date(-946771200000L + - (Math.abs(random.nextLong()) % (70L * 365 * 24 * 60 * 60 * 1000))); - } - - public static Note randomNote() { - InputStream inputStream = ClassLoader.getSystemResourceAsStream("test.text"); - - assert inputStream != null; - try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) { - String strLine; - long line = random.nextInt(49); - int count = 0; - while ((strLine = br.readLine()) != null) { - if (count == line) { - Note note = new Note(); - note.setNoteId(line); - note.setText(strLine); - return note; - } - count++; - } - } catch (IOException e) { - // ignore - } - // ignore - return null; - } - - private static String randomCompanyName() { - InputStream inputStream = ClassLoader.getSystemResourceAsStream("english.stop"); - - assert inputStream != null; - try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) { - String strLine; - int line = random.nextInt(570); - int count = 0; - while ((strLine = br.readLine()) != null) { - if (count == line) { - return strLine + System.nanoTime() + " inc."; - } - count++; - } - } catch (IOException e) { - // ignore - } - // ignore - return null; - } - - private static List departments() { - return new ArrayList() {{ - add("dev"); - add("hr"); - add("qa"); - add("dev-ops"); - add("sales"); - add("marketing"); - add("design"); - add("support"); - }}; - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ElemMatch.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ElemMatch.java deleted file mode 100644 index 0793025ef..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ElemMatch.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author Anindya Chatterjee - */ -@Data -public class ElemMatch implements Mappable { - private long id; - private String[] strArray; - private ProductScore[] productScores; - - @Override - public Document write(NitriteMapper mapper) { - List list = new ArrayList<>(); - if (productScores != null) { - for (ProductScore productScore : productScores) { - Document document = productScore.write(mapper); - list.add(document); - } - } - - return Document.createDocument("id", id) - .put("strArray", strArray) - .put("productScores", list); - } - - @Override - @SuppressWarnings("unchecked") - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Long.class); - strArray = document.get("strArray", String[].class); - List list = document.get("productScores", List.class); - if (list != null) { - productScores = new ProductScore[list.size()]; - for (int i = 0; i < list.size(); i++) { - productScores[i] = new ProductScore(); - productScores[i].read(mapper, list.get(i)); - } - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/Employee.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/Employee.java deleted file mode 100644 index 7683f99d4..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/Employee.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; - -import java.io.Serializable; -import java.util.Date; - -/** - * @author Anindya Chatterjee. - */ -@ToString -@EqualsAndHashCode -@Index(value = "joinDate", type = IndexType.NonUnique) -@Index(value = "address", type = IndexType.Fulltext) -@Index(value = "employeeNote.text", type = IndexType.Fulltext) -public class Employee implements Serializable, Mappable { - @Id - @Getter - @Setter - private Long empId; - - @Getter - @Setter - private Date joinDate; - - @Getter - @Setter - private String address; - - @Getter - @Setter - private transient Company company; - - @Getter - @Setter - private byte[] blob; - - @Getter - @Setter - private Note employeeNote; - - public Employee() { - } - - public Employee(Employee copy) { - empId = copy.empId; - joinDate = copy.joinDate; - address = copy.address; - company = copy.company; - blob = copy.blob; - employeeNote = copy.employeeNote; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("empId", empId) - .put("joinDate", joinDate) - .put("address", address) - .put("blob", blob) - .put("employeeNote", employeeNote != null ? employeeNote.write(mapper) : null); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - empId = document.get("empId", Long.class); - joinDate = document.get("joinDate", Date.class); - address = document.get("address", String.class); - blob = document.get("blob", byte[].class); - - if (document.get("employeeNote") != null) { - employeeNote = new Note(); - employeeNote.read(mapper, document.get("employeeNote", Document.class)); - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/Note.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/Note.java deleted file mode 100644 index a719aa4d8..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/Note.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.io.Serializable; - -/** - * @author Anindya Chatterjee. - */ -@EqualsAndHashCode -public class Note implements Serializable, Mappable { - @Getter - @Setter - private Long noteId; - @Getter - @Setter - private String text; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument().put("noteId", noteId).put("text", text); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - noteId = document.get("noteId", Long.class); - text = document.get("text", String.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ParentClass.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ParentClass.java deleted file mode 100644 index d6278e242..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ParentClass.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; - -import java.util.Date; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@Index(value = "date") -public class ParentClass extends SuperDuperClass { - @Id - protected Long id; - private Date date; - - @Override - public Document write(NitriteMapper mapper) { - return super.write(mapper) - .put("id", id) - .put("date", date); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - super.read(mapper, document); - id = document.get("id", Long.class); - date = document.get("date", Date.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/PersonEntity.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/PersonEntity.java deleted file mode 100644 index 419032405..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/PersonEntity.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Entity; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; - -import java.util.Date; -import java.util.UUID; - -/** - * @author Anindya Chatterjee - */ -@Data -@Entity(value = "MyPerson", indices = { - @Index(value = "name", type = IndexType.Fulltext), - @Index(value = "status", type = IndexType.NonUnique) -}) -public class PersonEntity implements Mappable { - @Id - private String uuid; - private String name; - private String status; - private PersonEntity friend; - private Date dateCreated; - - public PersonEntity() { - this.uuid = UUID.randomUUID().toString(); - this.dateCreated = new Date(); - } - - public PersonEntity(String name) { - this.uuid = UUID.randomUUID().toString(); - this.name = name; - this.dateCreated = new Date(); - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("uuid", uuid) - .put("name", name) - .put("status", status) - .put("friend", friend != null ? friend.write(mapper) : null) - .put("dateCreated", dateCreated); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - if (document != null) { - uuid = document.get("uuid", String.class); - name = document.get("name", String.class); - status = document.get("status", String.class); - dateCreated = document.get("dateCreated", Date.class); - friend = new PersonEntity(); - friend.read(mapper, document.get("friend", Document.class)); - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ProductScore.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ProductScore.java deleted file mode 100644 index 5515e45c9..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/ProductScore.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -public class ProductScore implements Mappable { - private String product; - private int score; - - public ProductScore() { - } - - public ProductScore(String product, int score) { - this.product = product; - this.score = score; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("product", product) - .put("score", score); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - product = document.get("product", String.class); - score = document.get("score", Integer.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/RepeatableIndexTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/RepeatableIndexTest.java deleted file mode 100644 index 9f4392384..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/RepeatableIndexTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Index; - -/** - * @author Anindya Chatterjee - */ -@Data -@Index(value = "firstName") -@Index(value = "age", type = IndexType.NonUnique) -@Index(value = "lastName", type = IndexType.Fulltext) -public class RepeatableIndexTest implements Mappable { - private String firstName; - private Integer age; - private String lastName; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("firstName", firstName) - .put("age", age) - .put("lastName", lastName); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - firstName = document.get("firstName", String.class); - age = document.get("age", Integer.class); - lastName = document.get("lastName", String.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/StressRecord.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/StressRecord.java deleted file mode 100644 index 5c301eeab..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/StressRecord.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class StressRecord implements Mappable { - @Id - private String firstName; - private boolean processed; - private String lastName; - private boolean failed; - private String notes; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument().put("firstName", firstName) - .put("processed", processed) - .put("lastName", lastName) - .put("failed", failed) - .put("notes", notes); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - firstName = document.get("firstName", String.class); - processed = document.get("processed", Boolean.class); - lastName = document.get("lastName", String.class); - failed = document.get("failed", Boolean.class); - notes = document.get("notes", String.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/SubEmployee.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/SubEmployee.java deleted file mode 100644 index 75b2b4f5c..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/SubEmployee.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.util.Date; - -/** - * @author Anindya Chatterjee. - */ -@EqualsAndHashCode -public class SubEmployee implements Mappable { - @Getter - @Setter - private Long empId; - - @Getter - @Setter - private Date joinDate; - - @Getter - @Setter - private String address; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("empId", empId) - .put("joinDate", joinDate) - .put("address", address); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - empId = document.get("empId", Long.class); - joinDate = document.get("joinDate", Date.class); - address = document.get("address", String.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/SuperDuperClass.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/SuperDuperClass.java deleted file mode 100644 index b132700bc..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/SuperDuperClass.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Index; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@Index(value = "text", type = IndexType.Fulltext) -public class SuperDuperClass implements Mappable { - private String text; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("text", text); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - text = document.get("text", String.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithCircularReference.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithCircularReference.java deleted file mode 100644 index a7f6c3a74..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithCircularReference.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.Getter; -import lombok.Setter; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithCircularReference { - private String name; - private WithCircularReference parent; -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithClassField.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithClassField.java deleted file mode 100644 index 276d07a6a..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithClassField.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithClassField implements Mappable { - @Id - private String name; - private Class clazz; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name) - .put("clazz", clazz); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - clazz = document.get("clazz", Class.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithCustomConstructor.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithCustomConstructor.java deleted file mode 100644 index 46d035652..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithCustomConstructor.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.Getter; -import lombok.Setter; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithCustomConstructor { - private String name; - private long number; - - public WithCustomConstructor(String name, long number) { - this.name = name; - this.number = number; - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithDateId.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithDateId.java deleted file mode 100644 index 6af52e206..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithDateId.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.util.Date; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@EqualsAndHashCode -public class WithDateId implements Mappable { - private Date id; - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name) - .put("id", id); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - id = document.get("id", Date.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithEmptyStringId.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithEmptyStringId.java deleted file mode 100644 index 6bbd6f35e..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithEmptyStringId.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithEmptyStringId implements Mappable { - @Id - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithFinalField.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithFinalField.java deleted file mode 100644 index e9dd39fb5..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithFinalField.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.exceptions.ObjectMappingException; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; - -/** - * @author Anindya Chatterjee. - */ -@Getter -public class WithFinalField implements Mappable { - private final long number; - @Setter - private String name; - - public WithFinalField() { - number = 2; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("name", name) - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - try { - Field field = getClass().getDeclaredField("number"); - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); - field.set(this, document.get("number", Long.class)); - } catch (Exception e) { - throw new ObjectMappingException("failed to set value"); - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithNitriteId.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithNitriteId.java deleted file mode 100644 index f26eb45c5..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithNitriteId.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee - */ -@Data -public class WithNitriteId implements Mappable { - @Id - public NitriteId idField; - public String name; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("idField", idField) - .put("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - idField = document.get("idField", NitriteId.class); - name = document.get("name", String.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithNullId.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithNullId.java deleted file mode 100644 index dd1995486..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithNullId.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithNullId implements Mappable { - @Id - private String name; - private long number; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("name", name) - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - number = document.get("number", Long.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithObjectId.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithObjectId.java deleted file mode 100644 index 86dc0baf3..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithObjectId.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithObjectId implements Mappable { - @Id - private WithOutId withOutId; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("withOutId", withOutId); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - withOutId = document.get("withOutId", WithOutId.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithOutGetterSetter.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithOutGetterSetter.java deleted file mode 100644 index 717918eb5..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithOutGetterSetter.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.EqualsAndHashCode; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@EqualsAndHashCode -public class WithOutGetterSetter implements Mappable { - private String name; - private long number; - - public WithOutGetterSetter() { - name = "test"; - number = 2; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name) - .put("number", number); - - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - number = document.get("number", Long.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithOutId.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithOutId.java deleted file mode 100644 index fd5447e47..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithOutId.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithOutId implements Comparable, Mappable { - private String name; - private long number; - - @Override - public int compareTo(WithOutId o) { - return Long.compare(number, o.number); - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("name", name) - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - number = document.get("number", Long.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithPrivateConstructor.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithPrivateConstructor.java deleted file mode 100644 index f64a0d181..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithPrivateConstructor.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.EqualsAndHashCode; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@EqualsAndHashCode -public class WithPrivateConstructor implements Mappable { - private String name; - private long number; - - private WithPrivateConstructor() { - name = "test"; - number = 2; - } - - public static WithPrivateConstructor create(final String name, final long number) { - WithPrivateConstructor obj = new WithPrivateConstructor(); - obj.number = number; - obj.name = name; - return obj; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name) - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - number = document.get("number", Long.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithPublicField.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithPublicField.java deleted file mode 100644 index 5660db416..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithPublicField.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -public class WithPublicField implements Mappable { - @Id - public String name; - public long number; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name) - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - number = document.get("number", Long.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithTransientField.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithTransientField.java deleted file mode 100644 index 87131a7d5..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/repository/data/WithTransientField.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithTransientField implements Mappable { - private transient String name; - @Id - private long number; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - number = document.get("number", Long.class); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/rocksdb/NitriteMapStressTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/rocksdb/NitriteMapStressTest.java deleted file mode 100644 index 26134ba70..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/rocksdb/NitriteMapStressTest.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2019-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.rocksdb; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.rocksdb.AbstractTest; -import org.dizitart.no2.store.NitriteMap; -import org.dizitart.no2.store.NitriteStore; -import org.junit.Test; - -import java.util.UUID; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee. - */ -public class NitriteMapStressTest extends AbstractTest { - - @Test - public void testWithInsertReadUpdate() { - NitriteStore nitriteStore = db.getStore(); - NitriteMap nitriteMap = nitriteStore.openMap("testWithInsertReadUpdate", String.class, Document.class); - - int count = 10000; - for (int i = 0; i < count; i++) { - Document record = Document.createDocument(); - record.put("firstName", UUID.randomUUID().toString()); - record.put("failed", false); - record.put("lastName", UUID.randomUUID().toString()); - record.put("processed", false); - - nitriteMap.put(UUID.randomUUID().toString(), record); - } - - for (Pair entry : nitriteMap.entries()) { - String key = entry.getFirst(); - Document record = entry.getSecond(); - - record.put("processed", true); - - nitriteMap.put(key, record); - } - - assertEquals(nitriteMap.size(), 10000); - } - - @Test - public void testNullKey() { - NitriteStore nitriteStore = db.getStore(); - NitriteMap nitriteMap = nitriteStore.openMap("testNullKey", String.class, Document.class); - nitriteMap.put(null, Document.createDocument()); - - assertNotNull(nitriteMap.get(null)); - assertEquals(nitriteMap.size(), 1); - - nitriteMap.put(null, Document.createDocument("first", 1)); - assertNotNull(nitriteMap.get(null)); - assertEquals(nitriteMap.size(), 1); - } - - @Test(expected = ValidationException.class) - public void testNullValue() { - NitriteStore nitriteStore = db.getStore(); - NitriteMap nitriteMap = nitriteStore.openMap("testNullValue", String.class, Document.class); - nitriteMap.put(null, null); - } - - @Test(expected = ValidationException.class) - public void testNullPutIfAbsent() { - NitriteStore nitriteStore = db.getStore(); - NitriteMap nitriteMap = nitriteStore.openMap("testNullPutIfAbsent", String.class, Document.class); - nitriteMap.putIfAbsent(null, null); - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/rocksdb/NitriteStoreEventTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/rocksdb/NitriteStoreEventTest.java deleted file mode 100644 index c50209f4f..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/rocksdb/NitriteStoreEventTest.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2019-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.rocksdb; - -import lombok.Data; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.rocksdb.Retry; -import org.dizitart.no2.rocksdb.RocksDBModule; -import org.dizitart.no2.store.events.EventInfo; -import org.dizitart.no2.store.events.StoreEventListener; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.concurrent.TimeUnit; - -import static org.awaitility.Awaitility.await; -import static org.dizitart.no2.rocksdb.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.rocksdb.TestUtil.deleteFile; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee - */ -public class NitriteStoreEventTest { - private String dbFile; - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void before() { - dbFile = getRandomTempDbFile(); - } - - @After - public void cleanup() throws IOException { - if (db != null && !db.isClosed()) { - db.close(); - } - - if (Files.exists(Paths.get(dbFile))) { - deleteFile(dbFile); - } - } - - @Test - public void testStoreEvents() { - TestStoreEventListener listener = new TestStoreEventListener(); - assertFalse(listener.opened); - assertFalse(listener.committed); - assertFalse(listener.closing); - assertFalse(listener.closed); - - RocksDBModule storeModule = RocksDBModule.withConfig() - .filePath(dbFile) - .addStoreEventListener(listener) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .fieldSeparator(".") - .openOrCreate(); - - await().atMost(1, TimeUnit.SECONDS).until(() -> listener.opened); - assertTrue(listener.opened); - assertFalse(listener.committed); - assertFalse(listener.closing); - assertFalse(listener.closed); - - db.commit(); - - await().atMost(1, TimeUnit.SECONDS).until(() -> listener.committed); - assertTrue(listener.opened); - assertTrue(listener.committed); - assertFalse(listener.closing); - assertFalse(listener.closed); - - db.close(); - - await().atMost(1, TimeUnit.SECONDS).until(() -> listener.closed); - assertTrue(listener.opened); - assertTrue(listener.committed); - assertTrue(listener.closing); - assertTrue(listener.closed); - - db.getStore().unsubscribe(listener); - } - - @Data - private static class TestStoreEventListener implements StoreEventListener { - private boolean opened; - private boolean committed; - private boolean closing; - private boolean closed; - - @Override - public void onEvent(EventInfo eventInfo) { - switch (eventInfo.getEvent()) { - case Opened: - opened = true; - break; - case Commit: - committed = true; - break; - case Closing: - closing = true; - break; - case Closed: - closed = true; - break; - } - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/transaction/TransactionCollectionTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/transaction/TransactionCollectionTest.java deleted file mode 100644 index 897985bfa..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/transaction/TransactionCollectionTest.java +++ /dev/null @@ -1,772 +0,0 @@ -package org.dizitart.no2.rocksdb.transaction; - -import com.github.javafaker.Faker; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.TransactionException; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.rocksdb.BaseCollectionTest; -import org.dizitart.no2.transaction.Session; -import org.dizitart.no2.transaction.Transaction; -import org.junit.Test; - -import java.util.*; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.collection.UpdateOptions.updateOptions; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -public class TransactionCollectionTest extends BaseCollectionTest { - - @Test - public void testCommitInsert() { - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - - Document document = createDocument("firstName", "John"); - txCol.insert(document); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); - assertNotEquals(collection.find(where("firstName").eq("John")).size(), 1); - - transaction.commit(); - - assertEquals(collection.find(where("firstName").eq("John")).size(), 1); - } - } - } - - @Test - public void testRollbackInsert() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - NitriteCollection txCol = transaction.getCollection("test"); - - Document document = createDocument("firstName", "John"); - Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); - txCol.insert(document); - txCol.insert(document2); - - // just to create UniqueConstraintViolation for rollback - collection.insert(createDocument("firstName", "Jane")); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertNotEquals(collection.find(where("firstName").eq("John")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - } - } - } - - @Test - public void testCommitUpdate() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - document.put("lastName", "Doe"); - - txCol.update(where("firstName").eq("John"), document, updateOptions(true)); - - assertEquals(txCol.find(where("lastName").eq("Doe")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - - transaction.commit(); - - assertEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - } - } - } - - @Test - public void testRollbackUpdate() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.insert(createDocument("firstName", "Jane")); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - NitriteCollection txCol = transaction.getCollection("test"); - - Document document = createDocument("firstName", "John"); - Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); - txCol.update(where("firstName").eq("Jane"), document2); - txCol.insert(document); - - // just to create UniqueConstraintViolation for rollback - collection.insert(createDocument("firstName", "John")); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); - assertEquals(txCol.find(where("lastName").eq("Doe")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(collection.find(where("firstName").eq("Jane")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - } - } - } - - @Test - public void testCommitRemove() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - - txCol.remove(where("firstName").eq("John")); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 0); - assertEquals(collection.find(where("firstName").eq("John")).size(), 1); - - transaction.commit(); - - assertEquals(collection.find(where("firstName").eq("John")).size(), 0); - } - } - } - - @Test - public void testRollbackRemove() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - - txCol.remove(where("firstName").eq("John")); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 0); - assertEquals(collection.find(where("firstName").eq("John")).size(), 1); - - txCol.insert(createDocument("firstName", "Jane")); - collection.insert(createDocument("firstName", "Jane")); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(collection.find(where("firstName").eq("John")).size(), 1); - assertEquals(collection.find(where("firstName").eq("Jane")).size(), 1); - } - } - } - - @Test - public void testCommitCreateIndex() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - txCol.createIndex("firstName", indexOptions(IndexType.Fulltext)); - - assertTrue(txCol.hasIndex("firstName")); - assertFalse(collection.hasIndex("firstName")); - - transaction.commit(); - - assertTrue(collection.hasIndex("firstName")); - } - } - } - - @Test - public void testRollbackCreateIndex() { - Document document = createDocument("firstName", "John"); - Document document2 = createDocument("firstName", "Jane"); - collection.insert(document); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - - txCol.createIndex("firstName", indexOptions(IndexType.Unique)); - - assertTrue(txCol.hasIndex("firstName")); - assertFalse(collection.hasIndex("firstName")); - - txCol.insert(document2); - collection.insert(document2); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertFalse(collection.hasIndex("firstName")); - } - } - } - - @Test - public void testCommitClear() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - txCol.clear(); - - assertEquals(0, txCol.size()); - assertEquals(1, collection.size()); - - transaction.commit(); - - assertEquals(0, collection.size()); - } - } - } - - @Test - public void testRollbackClear() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - Document document = createDocument("firstName", "John"); - Document document2 = createDocument("firstName", "Jane"); - collection.insert(document); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - - txCol.clear(); - - assertEquals(0, txCol.size()); - assertEquals(1, collection.size()); - - txCol.insert(document2); - collection.insert(document2); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(2, collection.size()); - } - } - } - - @Test - public void testCommitDropIndex() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - txCol.dropIndex("firstName"); - - assertFalse(txCol.hasIndex("firstName")); - assertTrue(collection.hasIndex("firstName")); - - transaction.commit(); - - assertFalse(collection.hasIndex("firstName")); - } - } - } - - @Test - public void testRollbackDropIndex() { - Document document = createDocument("firstName", "John").put("lastName", "Doe"); - Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); - collection.insert(document); - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - txCol.dropIndex("lastName"); - - assertFalse(txCol.hasIndex("lastName")); - assertTrue(collection.hasIndex("lastName")); - - txCol.insert(document2); - collection.insert(document2); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertTrue(collection.hasIndex("lastName")); - } - } - } - - @Test - public void testCommitDropAllIndices() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("lastName", indexOptions(IndexType.Unique)); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - txCol.dropAllIndices(); - - assertFalse(txCol.hasIndex("firstName")); - assertFalse(txCol.hasIndex("lastName")); - assertTrue(collection.hasIndex("firstName")); - assertTrue(collection.hasIndex("lastName")); - - transaction.commit(); - - assertFalse(collection.hasIndex("firstName")); - assertFalse(collection.hasIndex("lastName")); - } - } - } - - @Test - public void testRollbackDropAllIndices() { - Document document = createDocument("firstName", "John").put("lastName", "Doe"); - collection.insert(document); - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - txCol.dropAllIndices(); - - assertFalse(txCol.hasIndex("firstName")); - assertFalse(txCol.hasIndex("lastName")); - assertTrue(collection.hasIndex("firstName")); - assertTrue(collection.hasIndex("lastName")); - - txCol.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); - collection.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertTrue(collection.hasIndex("firstName")); - assertTrue(collection.hasIndex("lastName")); - } - } - } - - @Test - public void testCommitDropCollection() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - txCol.drop(); - - boolean expectedException = false; - try { - assertEquals(0, txCol.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - assertEquals(1, collection.size()); - - transaction.commit(); - - expectedException = false; - try { - assertEquals(0, collection.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - } - } - } - - @Test - public void testRollbackDropCollection() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - - txCol.drop(); - - boolean expectedException = false; - try { - assertEquals(0, txCol.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - assertEquals(1, collection.size()); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(1, collection.size()); - } - } - } - - @Test - public void testCommitSetAttribute() { - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - - Attributes attributes = new Attributes(); - attributes.setAttributes(Collections.singletonMap("key", "value")); - txCol.setAttributes(attributes); - - assertNull(collection.getAttributes()); - - transaction.commit(); - - assertEquals("value", collection.getAttributes().get("key")); - } - } - } - - @Test - public void testRollbackSetAttribute() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - NitriteCollection txCol = transaction.getCollection("test"); - - Attributes attributes = new Attributes(); - Map map = new HashMap<>(); - map.put("key", "value"); - attributes.setAttributes(map); - txCol.setAttributes(attributes); - - txCol.insert(createDocument("firstName", "John")); - txCol.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); - - assertNull(collection.getAttributes()); - - // just to create UniqueConstraintViolation for rollback - collection.insert(createDocument("firstName", "Jane")); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertNull(collection.getAttributes().get("key")); - } - } - } - - @Test - public void testConcurrentInsertAndRemove() { - NitriteCollection collection = db.getCollection("test"); - collection.createIndex("firstName", indexOptions(IndexType.NonUnique)); - collection.createIndex("id", indexOptions(IndexType.Unique)); - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - final long fi = i; - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - NitriteCollection txCol = transaction.getCollection("test"); - - for (int j = 0; j < 10; j++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("lastName", faker.name().lastName()) - .put("id", j + (fi * 10)); - txCol.insert(document); - } - - txCol.remove(where("id").eq(2 + (fi * 10))); - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(90, collection.size()); - } - } - - @Test - public void testConcurrentInsert() { - NitriteCollection collection = db.getCollection("test"); - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - NitriteCollection txCol = transaction.getCollection("test"); - - for (int j = 0; j < 10; j++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("lastName", faker.name().lastName()); - txCol.insert(document); - } - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(100, collection.size()); - } - } - - @Test - public void testConcurrentUpdate() { - NitriteCollection collection = db.getCollection("test"); - for (int i = 0; i < 10; i++) { - Document document = createDocument("id", i); - collection.insert(document); - } - - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - NitriteCollection txCol = transaction.getCollection("test"); - - for (int j = 0; j < 10; j++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("lastName", faker.name().lastName()) - .put("id", j); - txCol.update(where("id").eq(j), document, updateOptions(true)); - } - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(10, collection.size()); - } - } - - @Test - public void testTransactionOnDifferentCollections() { - NitriteCollection col1 = db.getCollection("test1"); - NitriteCollection col2 = db.getCollection("test2"); - NitriteCollection col3 = db.getCollection("test3"); - col3.createIndex("id", indexOptions(IndexType.Unique)); - - Faker faker = new Faker(); - - try(Session session = db.createSession()) { - Transaction transaction = session.beginTransaction(); - - NitriteCollection test1 = transaction.getCollection("test1"); - NitriteCollection test2 = transaction.getCollection("test2"); - NitriteCollection test3 = transaction.getCollection("test3"); - - for (int i = 0; i < 10; i++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", i); - test1.insert(document); - - document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 10); - test2.insert(document); - - document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 20); - test3.insert(document); - } - - assertEquals(test1.size(), 10); - assertEquals(test2.size(), 10); - assertEquals(test3.size(), 10); - - assertEquals(col1.size(), 0); - assertEquals(col2.size(), 0); - assertEquals(col3.size(), 0); - - transaction.commit(); - - assertEquals(col1.size(), 10); - assertEquals(col2.size(), 10); - assertEquals(col3.size(), 10); - } - - - Transaction transaction = null; - try (Session session = db.createSession()) { - transaction = session.beginTransaction(); - - NitriteCollection test1 = transaction.getCollection("test1"); - NitriteCollection test2 = transaction.getCollection("test2"); - NitriteCollection test3 = transaction.getCollection("test3"); - - for (int i = 0; i < 10; i++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 30); - test1.insert(document); - - document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 40); - test2.insert(document); - - document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 50); - test3.insert(document); - } - - assertEquals(test1.size(), 20); - assertEquals(test2.size(), 20); - assertEquals(test3.size(), 20); - - assertEquals(col1.size(), 10); - assertEquals(col2.size(), 10); - assertEquals(col3.size(), 10); - - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", 52); - col3.insert(document); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - - assertEquals(col1.size(), 10); - assertEquals(col2.size(), 10); - assertEquals(col3.size(), 11); // last document added - } - } - - @Test(expected = TransactionException.class) - public void testFailureOnClosedTransaction() { - try(Session session = db.createSession()) { - Transaction transaction = session.beginTransaction(); - NitriteCollection col = transaction.getCollection("test"); - col.insert(createDocument("id", 1)); - transaction.commit(); - - col.insert(createDocument("id", 2)); - fail(); - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/transaction/TransactionRepositoryTest.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/transaction/TransactionRepositoryTest.java deleted file mode 100644 index 23d05aa3c..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/transaction/TransactionRepositoryTest.java +++ /dev/null @@ -1,810 +0,0 @@ -package org.dizitart.no2.rocksdb.transaction; - -import com.github.javafaker.Faker; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.TransactionException; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.rocksdb.repository.BaseObjectRepositoryTest; -import org.dizitart.no2.rocksdb.repository.data.SubEmployee; -import org.dizitart.no2.transaction.Session; -import org.dizitart.no2.transaction.Transaction; -import org.junit.Test; - -import java.util.*; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -public class TransactionRepositoryTest extends BaseObjectRepositoryTest { - - @Test - public void testCommitInsert() { - ObjectRepository repository = db.getRepository(TxData.class); - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - TxData txData1 = new TxData(); - txData1.setId(1L); - txData1.setName("John"); - - txRepo.insert(txData1); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 1); - assertNotEquals(repository.find(where("name").eq("John")).size(), 1); - - transaction.commit(); - - assertEquals(repository.find(where("name").eq("John")).size(), 1); - } - } - } - - @Test - public void testRollbackInsert() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - TxData txData1 = new TxData(); - txData1.setId(1L); - txData1.setName("John"); - - TxData txData2 = new TxData(); - txData2.setId(2L); - txData2.setName("Jane"); - - txRepo.insert(txData1, txData2); - - txData2.setName("Molly"); - repository.insert(txData2); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 1); - assertEquals(repository.find(where("name").eq("John")).size(), 0); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(repository.find(where("name").eq("John")).size(), 0); - assertEquals(repository.find(where("name").eq("Molly")).size(), 1); - } - } - } - - @Test - public void testCommitUpdate() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(new TxData(1L, "John")); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - TxData txData1 = new TxData(1L, "Jane"); - txRepo.update(txData1, true); - - assertEquals(txRepo.find(where("name").eq("Jane")).size(), 1); - assertNotEquals(repository.find(where("name").eq("Jane")).size(), 1); - - transaction.commit(); - - assertEquals(repository.find(where("name").eq("Jane")).size(), 1); - } - } - } - - @Test - public void testRollbackUpdate() { - ObjectRepository repository = db.getRepository(TxData.class, "rollback"); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(new TxData(1L, "Jane")); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - ObjectRepository txRepo = transaction.getRepository(TxData.class, "rollback"); - - TxData txData1 = new TxData(); - txData1.setId(2L); - txData1.setName("John"); - - TxData txData2 = new TxData(); - txData2.setId(1L); - txData2.setName("Jane Doe"); - txRepo.update(txData2); - txRepo.insert(txData1); - - // just to create UniqueConstraintViolation for rollback - repository.insert(txData1); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 1); - assertEquals(txRepo.find(where("name").eq("Jane Doe")).size(), 1); - assertNotEquals(repository.find(where("name").eq("Jane Doe")).size(), 1); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(repository.find(where("name").eq("Jane")).size(), 1); - assertNotEquals(repository.find(where("name").eq("Jane Doe")).size(), 1); - } - } - } - - @Test - public void testCommitRemove() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - txRepo.remove(where("name").eq("John")); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 0); - assertEquals(repository.find(where("name").eq("John")).size(), 1); - - transaction.commit(); - - assertEquals(repository.find(where("name").eq("John")).size(), 0); - } - } - } - - @Test - public void testRollbackRemove() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - TxData txData1 = new TxData(1L, "John"); - repository.insert(txData1); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - txRepo.remove(where("name").eq("John")); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 0); - assertEquals(repository.find(where("name").eq("John")).size(), 1); - - TxData txData2 = new TxData(2L, "Jane"); - txRepo.insert(txData2); - repository.insert(txData2); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(repository.find(where("name").eq("John")).size(), 1); - assertEquals(repository.find(where("name").eq("Jane")).size(), 1); - } - } - } - - @Test - public void testCommitCreateIndex() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.createIndex("name", indexOptions(IndexType.Fulltext)); - - assertTrue(txRepo.hasIndex("name")); - assertFalse(repository.hasIndex("name")); - - transaction.commit(); - - assertTrue(repository.hasIndex("name")); - } - } - } - - @Test - public void testRollbackCreateIndex() { - TxData txData1 = new TxData(1L, "John"); - TxData txData2 = new TxData(2L, "Jane"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.createIndex("name", indexOptions(IndexType.Fulltext)); - - assertTrue(txRepo.hasIndex("name")); - assertFalse(repository.hasIndex("name")); - - txRepo.insert(txData2); - repository.insert(txData2); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertFalse(repository.hasIndex("name")); - } - } - } - - @Test - public void testCommitClear() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.clear(); - - assertEquals(0, txRepo.size()); - assertEquals(1, repository.size()); - - transaction.commit(); - - assertEquals(0, repository.size()); - } - } - } - - @Test - public void testRollbackClear() { - TxData txData1 = new TxData(1L, "John"); - TxData txData2 = new TxData(2L, "Jane"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.clear(); - - assertEquals(0, txRepo.size()); - assertEquals(1, repository.size()); - - txRepo.insert(txData2); - repository.insert(txData2); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(2, repository.size()); - } - } - } - - @Test - public void testCommitDropIndex() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.dropIndex("name"); - - assertFalse(txRepo.hasIndex("name")); - assertTrue(repository.hasIndex("name")); - - transaction.commit(); - - assertFalse(repository.hasIndex("name")); - } - } - } - - @Test - public void testRollbackDropIndex() { - TxData txData1 = new TxData(1L, "John"); - TxData txData2 = new TxData(2L, "Jane"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.dropIndex("name"); - - assertFalse(txRepo.hasIndex("name")); - assertTrue(repository.hasIndex("name")); - - txRepo.insert(txData2); - repository.insert(txData2); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertTrue(repository.hasIndex("name")); - } - } - } - - @Test - public void testCommitDropAllIndices() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.dropAllIndices(); - - assertFalse(txRepo.hasIndex("name")); - assertTrue(repository.hasIndex("name")); - - transaction.commit(); - - assertFalse(repository.hasIndex("name")); - } - } - } - - @Test - public void testRollbackDropAllIndices() { - TxData txData1 = new TxData(1L, "John"); - TxData txData2 = new TxData(2L, "Jane"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.dropAllIndices(); - - assertFalse(txRepo.hasIndex("name")); - assertTrue(repository.hasIndex("name")); - - txRepo.insert(txData2); - repository.insert(txData2); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertTrue(repository.hasIndex("name")); - } - } - } - - @Test - public void testCommitDropRepository() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.drop(); - - boolean expectedException = false; - try { - assertEquals(0, txRepo.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - assertEquals(1, repository.size()); - - transaction.commit(); - - expectedException = false; - try { - assertEquals(0, repository.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - } - } - } - - @Test - public void testRollbackDropRepository() { - TxData txData1 = new TxData(1L, "John"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.drop(); - - boolean expectedException = false; - try { - assertEquals(0, txRepo.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - assertEquals(1, repository.size()); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(1, repository.size()); - } - } - } - - @Test - public void testCommitSetAttribute() { - ObjectRepository repository = db.getRepository(TxData.class); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - Attributes attributes = new Attributes(); - attributes.setAttributes(Collections.singletonMap("key", "value")); - txRepo.setAttributes(attributes); - - assertNull(repository.getAttributes()); - - transaction.commit(); - - assertEquals("value", repository.getAttributes().get("key")); - } - } - } - - @Test - public void testRollbackSetAttribute() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - Attributes attributes = new Attributes(); - Map map = new HashMap<>(); - map.put("key", "value"); - attributes.setAttributes(map); - txRepo.setAttributes(attributes); - - txRepo.insert(new TxData(1L, "John")); - txRepo.insert(new TxData(2L, "Jane")); - - assertNull(repository.getAttributes()); - - // just to create UniqueConstraintViolation for rollback - repository.insert(new TxData(2L, "Jane")); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 1); - assertNotEquals(repository.find(where("name").eq("John")).size(), 1); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertNull(repository.getAttributes().get("key")); - } - } - } - - @Test - public void testConcurrentInsertAndRemove() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.NonUnique)); - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - final long fi = i; - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - for (long j = 0; j < 10; j++) { - TxData txData = new TxData(j + (fi * 10), faker.name().name()); - txRepo.insert(txData); - } - - txRepo.remove(where("id").eq(2L + (fi * 10))); - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(90, repository.size()); - } - } - - @Test - public void testConcurrentInsert() { - ObjectRepository repository = db.getRepository(TxData.class); - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - final long fi = i; - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - for (long j = 0; j < 10; j++) { - TxData txData = new TxData(j + (fi * 10), faker.name().name()); - txRepo.insert(txData); - } - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(100, repository.size()); - } - } - - @Test - public void testConcurrentUpdate() { - ObjectRepository repository = db.getRepository(TxData.class); - Faker faker = new Faker(); - for (long j = 0; j < 10; j++) { - TxData txData = new TxData(j, faker.name().name()); - repository.insert(txData); - } - - List> futures = new ArrayList<>(); - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - for (int j = 0; j < 10; j++) { - TxData txData = new TxData((long) j, faker.name().name()); - txRepo.update(where("id").eq(j), txData); - } - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(10, repository.size()); - } - } - - @Test - public void testTransactionOnDifferentRepositoriesAndCollections() { - ObjectRepository repo1 = db.getRepository(TxData.class); - ObjectRepository repo2 = db.getRepository(TxData.class, "2"); - ObjectRepository repo3 = db.getRepository(SubEmployee.class); - NitriteCollection col1 = db.getCollection("test1"); - col1.createIndex("id", indexOptions(IndexType.Unique)); - - Faker faker = new Faker(); - - try(Session session = db.createSession()) { - Transaction transaction = session.beginTransaction(); - - ObjectRepository txRepo1 = transaction.getRepository(TxData.class); - ObjectRepository txRepo2 = transaction.getRepository(TxData.class, "2"); - ObjectRepository txRepo3 = transaction.getRepository(SubEmployee.class); - NitriteCollection test1 = transaction.getCollection("test1"); - - for (long i = 0; i < 10; i++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", i); - test1.insert(document); - - TxData txData1 = new TxData(i, faker.name().name()); - txRepo1.insert(txData1); - - TxData txData2 = new TxData(i + 10, faker.name().name()); - txRepo2.insert(txData2); - - SubEmployee employee = new SubEmployee(); - employee.setAddress(faker.address().fullAddress()); - employee.setEmpId(i); - employee.setJoinDate(faker.date().birthday()); - txRepo3.insert(employee); - } - - assertEquals(test1.size(), 10); - assertEquals(txRepo1.size(), 10); - assertEquals(txRepo2.size(), 10); - assertEquals(txRepo3.size(), 10); - - assertEquals(col1.size(), 0); - assertEquals(repo1.size(), 0); - assertEquals(repo2.size(), 0); - assertEquals(repo3.size(), 0); - - transaction.commit(); - - assertEquals(col1.size(), 10); - assertEquals(repo1.size(), 10); - assertEquals(repo2.size(), 10); - assertEquals(repo3.size(), 10); - } - - Transaction transaction = null; - try (Session session = db.createSession()) { - transaction = session.beginTransaction(); - - ObjectRepository txRepo1 = transaction.getRepository(TxData.class); - ObjectRepository txRepo2 = transaction.getRepository(TxData.class, "2"); - ObjectRepository txRepo3 = transaction.getRepository(SubEmployee.class); - NitriteCollection test1 = transaction.getCollection("test1"); - - for (long i = 0; i < 10; i++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 10); - test1.insert(document); - - TxData txData1 = new TxData(i + 10, faker.name().name()); - txRepo1.insert(txData1); - - TxData txData2 = new TxData(i + 20, faker.name().name()); - txRepo2.insert(txData2); - - SubEmployee employee = new SubEmployee(); - employee.setAddress(faker.address().fullAddress()); - employee.setEmpId(i + 10); - employee.setJoinDate(faker.date().birthday()); - txRepo3.insert(employee); - } - - assertEquals(test1.size(), 20); - assertEquals(txRepo1.size(), 20); - assertEquals(txRepo2.size(), 20); - assertEquals(txRepo3.size(), 20); - - assertEquals(col1.size(), 10); - assertEquals(repo1.size(), 10); - assertEquals(repo2.size(), 10); - assertEquals(repo3.size(), 10); - - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", 12L); - col1.insert(document); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - - assertEquals(col1.size(), 11); // last doc added - assertEquals(repo1.size(), 10); - assertEquals(repo2.size(), 10); - assertEquals(repo3.size(), 10); - } - } - - @Test(expected = TransactionException.class) - public void testFailureOnClosedTransaction() { - try(Session session = db.createSession()) { - Transaction transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.insert(new TxData(1L, "John")); - transaction.commit(); - - txRepo.insert(new TxData(2L, "Jane")); - fail(); - } - } -} diff --git a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/transaction/TxData.java b/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/transaction/TxData.java deleted file mode 100644 index 27d0d8183..000000000 --- a/nitrite-rocksdb-adapter/src/test/java/org/dizitart/no2/rocksdb/transaction/TxData.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rocksdb.transaction; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -class TxData implements Mappable { - @Id - private Long id; - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("id", id) - .put("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Long.class); - name = document.get("name", String.class); - } -} diff --git a/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/FluentFilter.java b/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/FluentFilter.java index bbafe16f1..1793e8564 100644 --- a/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/FluentFilter.java +++ b/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/FluentFilter.java @@ -22,7 +22,10 @@ import org.locationtech.jts.geom.Point; /** + * Fluent filter api for spatial data + * * @author Anindya Chatterjee + * @since 4.0 */ public class FluentFilter { private String field; @@ -30,24 +33,60 @@ public class FluentFilter { private FluentFilter() { } + /** + * Where clause for fluent filter. + * + * @param field the field + * @return the fluent filter + */ public static FluentFilter where(String field) { FluentFilter filter = new FluentFilter(); filter.field = field; return filter; } + /** + * Creates an spatial filter which matches documents where the spatial data + * of a field intersects the specified {@link Geometry} value. + * + * @param geometry the geometry + * @return the filter + */ public Filter intersects(Geometry geometry) { return new IntersectsFilter(field, geometry); } + /** + * Creates a spatial filter which matches documents where the spatial data + * of a field is within the specified {@link Geometry} value. + * + * @param geometry the geometry + * @return the filter + */ public Filter within(Geometry geometry) { return new WithinFilter(field, geometry); } + /** + * Creates a spatial filter which matches documents where the spatial data + * of a field is near the specified coordinate. + * + * @param point the point + * @param distance the distance + * @return the filter + */ public Filter near(Coordinate point, Double distance) { return new NearFilter(field, point, distance); } + /** + * Creates a spatial filter which matches documents where the spatial data + * of a field is near the specified point. + * + * @param point the point + * @param distance the distance + * @return the filter + */ public Filter near(Point point, Double distance) { return new NearFilter(field, point, distance); } diff --git a/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/IntersectsFilter.java b/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/IntersectsFilter.java index d20f7b6a0..89a1f7863 100644 --- a/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/IntersectsFilter.java +++ b/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/IntersectsFilter.java @@ -16,15 +16,13 @@ package org.dizitart.no2.spatial; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.index.IndexMap; import org.locationtech.jts.geom.Geometry; -import java.util.LinkedHashSet; -import java.util.Set; +import java.util.List; /** + * @since 4.0 * @author Anindya Chatterjee */ class IntersectsFilter extends SpatialFilter { @@ -33,16 +31,13 @@ protected IntersectsFilter(String field, Geometry geometry) { } @Override - protected Set findIndexedIdSet() { - if (getIsFieldIndexed()) { - if (getIndexer() instanceof SpatialIndexer && getValue() != null) { - SpatialIndexer spatialIndexer = (SpatialIndexer) getIndexer(); - RecordStream idSet = spatialIndexer.findIntersects(getCollectionName(), getField(), getValue()); - return idSet.toSet(); - } else { - throw new FilterException(getValue() + " is not a Geometry"); - } - } - return new LinkedHashSet<>(); + public List applyOnIndex(IndexMap indexMap) { + // calculated from SpatialIndex + return null; + } + + @Override + public String toString() { + return "(" + getField() + " intersects " + getValue() + ")"; } } diff --git a/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/NearFilter.java b/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/NearFilter.java index 4ae677884..fe4d4764e 100644 --- a/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/NearFilter.java +++ b/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/NearFilter.java @@ -22,6 +22,7 @@ import org.locationtech.jts.util.GeometricShapeFactory; /** + * @since 4.0 * @author Anindya Chatterjee */ class NearFilter extends WithinFilter { @@ -40,4 +41,9 @@ private static Geometry createCircle(Coordinate center, double radius) { shapeFactory.setSize(radius * 2); return shapeFactory.createCircle(); } + + @Override + public String toString() { + return "(" + getField() + " nears " + getValue() + ")"; + } } diff --git a/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/NitriteBoundingBox.java b/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/NitriteBoundingBox.java index 53ba2030a..f8249b568 100644 --- a/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/NitriteBoundingBox.java +++ b/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/NitriteBoundingBox.java @@ -26,6 +26,8 @@ import java.io.ObjectOutputStream; /** + * + * @since 4.0 * @author Anindya Chatterjee */ @Data diff --git a/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/SpatialFilter.java b/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/SpatialFilter.java index 20118b30f..5c8e8fe4d 100644 --- a/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/SpatialFilter.java +++ b/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/SpatialFilter.java @@ -19,19 +19,24 @@ import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.filters.IndexAwareFilter; -import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.filters.IndexOnlyFilter; import org.locationtech.jts.geom.Geometry; -import java.util.Set; - /** + * Represents a spatial filter. + * + * @since 4.0 * @author Anindya Chatterjee */ -public abstract class SpatialFilter extends IndexAwareFilter { +public abstract class SpatialFilter extends IndexOnlyFilter { private final Geometry geometry; + /** + * Instantiates a new {@link SpatialFilter}. + * + * @param field the field + * @param geometry the geometry + */ protected SpatialFilter(String field, Geometry geometry) { super(field, geometry); this.geometry = geometry; @@ -43,12 +48,18 @@ public Geometry getValue() { } @Override - protected Set findIdSet(NitriteMap collection) { - throw new FilterException("spatial filters cannot be applied on _id field"); + public boolean apply(Pair element) { + return false; } @Override - public boolean apply(Pair element) { - throw new FilterException(getField() + " is not indexed with spatial index"); + public String supportedIndexType() { + return SpatialIndexer.SPATIAL_INDEX; + } + + @Override + public boolean canBeGrouped(IndexOnlyFilter other) { + return other instanceof SpatialFilter + && other.getField().equals(getField()); } } diff --git a/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/SpatialIndex.java b/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/SpatialIndex.java new file mode 100644 index 000000000..eb2edd966 --- /dev/null +++ b/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/SpatialIndex.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.spatial; + +import lombok.Getter; +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.FieldValues; +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.filters.ComparableFilter; +import org.dizitart.no2.filters.IndexScanFilter; +import org.dizitart.no2.index.BoundingBox; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.NitriteIndex; +import org.dizitart.no2.store.NitriteRTree; +import org.dizitart.no2.store.NitriteStore; +import org.locationtech.jts.geom.Geometry; + +import java.util.LinkedHashSet; +import java.util.List; + +import static org.dizitart.no2.common.util.IndexUtils.deriveIndexMapName; + +/** + * Represents a spatial index in nitrite. + * + * @since 4.0 + * @author Anindya Chatterjee + */ +public class SpatialIndex implements NitriteIndex { + @Getter + private final IndexDescriptor indexDescriptor; + private final NitriteStore nitriteStore; + private final NitriteConfig nitriteConfig; + + /** + * Instantiates a new {@link SpatialIndex}. + * + * @param indexDescriptor the index descriptor + * @param nitriteConfig the nitrite config + */ + public SpatialIndex(IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig) { + this.indexDescriptor = indexDescriptor; + this.nitriteConfig = nitriteConfig; + this.nitriteStore = nitriteConfig.getNitriteStore(); + } + + @Override + public void write(FieldValues fieldValues) { + Fields fields = fieldValues.getFields(); + List fieldNames = fields.getFieldNames(); + + String firstField = fieldNames.get(0); + Object element = fieldValues.get(firstField); + + NitriteRTree indexMap = findIndexMap(); + if (element == null) { + indexMap.add(null, fieldValues.getNitriteId()); + } else { + Geometry geometry = parseGeometry(firstField, element); + BoundingBox boundingBox = new NitriteBoundingBox(geometry); + indexMap.add(boundingBox, fieldValues.getNitriteId()); + } + } + + @Override + public void remove(FieldValues fieldValues) { + Fields fields = fieldValues.getFields(); + List fieldNames = fields.getFieldNames(); + + String firstField = fieldNames.get(0); + Object element = fieldValues.get(firstField); + + NitriteRTree indexMap = findIndexMap(); + if (element == null) { + indexMap.remove(null, fieldValues.getNitriteId()); + } else { + Geometry geometry = parseGeometry(firstField, element); + BoundingBox boundingBox = new NitriteBoundingBox(geometry); + indexMap.remove(boundingBox, fieldValues.getNitriteId()); + } + } + + @Override + public void drop() { + NitriteRTree indexMap = findIndexMap(); + indexMap.clear(); + indexMap.drop(); + } + + @Override + public LinkedHashSet findNitriteIds(FindPlan findPlan) { + IndexScanFilter indexScanFilter = findPlan.getIndexScanFilter(); + if (indexScanFilter == null + || indexScanFilter.getFilters() == null + || indexScanFilter.getFilters().isEmpty()) { + throw new FilterException("no spatial filter found"); + } + + List filters = indexScanFilter.getFilters(); + ComparableFilter filter = filters.get(0); + + if (!(filter instanceof SpatialFilter)) { + throw new FilterException("spatial filter must be the first filter for index scan"); + } + + RecordStream keys = null; + NitriteRTree indexMap = findIndexMap(); + + SpatialFilter spatialFilter = (SpatialFilter) filter; + Geometry geometry = spatialFilter.getValue(); + BoundingBox boundingBox = new NitriteBoundingBox(geometry); + + if (filter instanceof WithinFilter) { + keys = indexMap.findContainedKeys(boundingBox); + } else if (filter instanceof IntersectsFilter) { + keys = indexMap.findIntersectingKeys(boundingBox); + } + + LinkedHashSet nitriteIds = new LinkedHashSet<>(); + if (keys != null) { + for (NitriteId nitriteId : keys) { + nitriteIds.add(nitriteId); + } + } + + return nitriteIds; + } + + private NitriteRTree findIndexMap() { + String mapName = deriveIndexMapName(indexDescriptor); + return nitriteStore.openRTree(mapName, BoundingBox.class, Geometry.class); + } + + private Geometry parseGeometry(String field, Object fieldValue) { + if (fieldValue == null) return null; + if (fieldValue instanceof String) { + return nitriteConfig.nitriteMapper().convert(fieldValue, Geometry.class); + } else if (fieldValue instanceof Geometry) { + return (Geometry) fieldValue; + } + throw new IndexingException("field " + field + " does not contain Geometry data"); + } +} diff --git a/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/SpatialIndexer.java b/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/SpatialIndexer.java index fe26b59eb..091766b57 100644 --- a/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/SpatialIndexer.java +++ b/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/SpatialIndexer.java @@ -17,96 +17,85 @@ package org.dizitart.no2.spatial; import org.dizitart.no2.NitriteConfig; -import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.FindPlan; import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.FieldValues; +import org.dizitart.no2.common.Fields; import org.dizitart.no2.exceptions.IndexingException; -import org.dizitart.no2.index.BoundingBox; -import org.dizitart.no2.index.Indexer; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.store.NitriteMap; -import org.dizitart.no2.store.NitriteRTree; -import org.dizitart.no2.store.NitriteStore; -import org.locationtech.jts.geom.Geometry; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.NitriteIndexer; + +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** + * Represents a spatial data indexer. + * * @author Anindya Chatterjee - * @since 4.0.0 + * @since 4.0 */ -public class SpatialIndexer implements Indexer { - public static final String SpatialIndex = "Spatial"; - - private NitriteMapper nitriteMapper; - private NitriteStore nitriteStore; - - public SpatialIndexer clone() throws CloneNotSupportedException { - return (SpatialIndexer) super.clone(); - } - - public RecordStream findWithin(String collectionName, String field, Geometry geometry) { - NitriteRTree indexMap = getIndexMap(collectionName, field); - BoundingBox boundingBox = new NitriteBoundingBox(geometry); - return indexMap.findContainedKeys(boundingBox); - } +public class SpatialIndexer implements NitriteIndexer { + /** + * Spatial index type. + */ + public static final String SPATIAL_INDEX = "Spatial"; + private final Map indexRegistry; - public RecordStream findIntersects(String collectionName, String field, Geometry geometry) { - NitriteRTree indexMap = getIndexMap(collectionName, field); - BoundingBox boundingBox = new NitriteBoundingBox(geometry); - return indexMap.findIntersectingKeys(boundingBox); + /** + * Instantiates a new {@link SpatialIndexer}. + */ + public SpatialIndexer() { + this.indexRegistry = new ConcurrentHashMap<>(); } @Override public String getIndexType() { - return SpatialIndex; + return SPATIAL_INDEX; } @Override - public void writeIndex(NitriteMap collection, NitriteId nitriteId, String field, Object fieldValue) { - if (fieldValue == null) return; - NitriteRTree indexMap = getIndexMap(collection.getName(), field); - Geometry geometry = parseGeometry(field, fieldValue); - BoundingBox boundingBox = new NitriteBoundingBox(geometry); - indexMap.add(boundingBox, nitriteId); + public void validateIndex(Fields fields) { + if (fields.getFieldNames().size() > 1) { + throw new IndexingException("spatial index can only be created on a single field"); + } } @Override - public void removeIndex(NitriteMap collection, NitriteId nitriteId, String field, Object fieldValue) { - if (fieldValue == null) return; - NitriteRTree indexMap = getIndexMap(collection.getName(), field); - Geometry geometry = parseGeometry(field, fieldValue); - BoundingBox boundingBox = new NitriteBoundingBox(geometry); - indexMap.remove(boundingBox, nitriteId); + public void dropIndex(IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig) { + SpatialIndex spatialIndex = findSpatialIndex(indexDescriptor, nitriteConfig); + spatialIndex.drop(); } @Override - public void updateIndex(NitriteMap collection, NitriteId nitriteId, String field, Object newValue, Object oldValue) { - removeIndex(collection, nitriteId, field, oldValue); - writeIndex(collection, nitriteId, field, newValue); + public void writeIndexEntry(FieldValues fieldValues, IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig) { + SpatialIndex spatialIndex = findSpatialIndex(indexDescriptor, nitriteConfig); + spatialIndex.write(fieldValues); } @Override - public void dropIndex(NitriteMap collection, String field) { - // no action required + public void removeIndexEntry(FieldValues fieldValues, IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig) { + SpatialIndex spatialIndex = findSpatialIndex(indexDescriptor, nitriteConfig); + spatialIndex.remove(fieldValues); } @Override - public void initialize(NitriteConfig nitriteConfig) { - this.nitriteStore = nitriteConfig.getNitriteStore(); - this.nitriteMapper = nitriteConfig.nitriteMapper(); + public LinkedHashSet findByFilter(FindPlan findPlan, NitriteConfig nitriteConfig) { + SpatialIndex spatialIndex = findSpatialIndex(findPlan.getIndexDescriptor(), nitriteConfig); + return spatialIndex.findNitriteIds(findPlan); } - private NitriteRTree getIndexMap(String collectionName, String field) { - String mapName = getIndexMapName(collectionName, field); - return nitriteStore.openRTree(mapName, BoundingBox.class, Geometry.class); + @Override + public void initialize(NitriteConfig nitriteConfig) { } - private Geometry parseGeometry(String field, Object fieldValue) { - if (fieldValue == null) return null; - if (fieldValue instanceof String) { - return nitriteMapper.convert(fieldValue, Geometry.class); - } else if (fieldValue instanceof Geometry) { - return (Geometry) fieldValue; + private SpatialIndex findSpatialIndex(IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig) { + if (indexRegistry.containsKey(indexDescriptor)) { + return indexRegistry.get(indexDescriptor); } - throw new IndexingException("field " + field + " does not contain Geometry data"); + + SpatialIndex nitriteIndex = new SpatialIndex(indexDescriptor, nitriteConfig); + indexRegistry.put(indexDescriptor, nitriteIndex); + return nitriteIndex; } } diff --git a/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/SpatialModule.java b/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/SpatialModule.java index a556977a2..b15ae57f2 100644 --- a/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/SpatialModule.java +++ b/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/SpatialModule.java @@ -16,12 +16,17 @@ package org.dizitart.no2.spatial; -import org.dizitart.no2.module.NitriteModule; -import org.dizitart.no2.module.NitritePlugin; +import org.dizitart.no2.common.module.NitriteModule; +import org.dizitart.no2.common.module.NitritePlugin; import java.util.Set; +import static org.dizitart.no2.common.util.Iterables.setOf; + /** + * A nitrite module to enable spatial data indexing. + * + * @since 4.0 * @author Anindya Chatterjee */ public class SpatialModule implements NitriteModule { diff --git a/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/WithinFilter.java b/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/WithinFilter.java index 842043496..fe25ea741 100644 --- a/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/WithinFilter.java +++ b/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/WithinFilter.java @@ -16,15 +16,13 @@ package org.dizitart.no2.spatial; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.index.IndexMap; import org.locationtech.jts.geom.Geometry; -import java.util.LinkedHashSet; -import java.util.Set; +import java.util.List; /** + * @since 4.0 * @author Anindya Chatterjee */ class WithinFilter extends SpatialFilter { @@ -33,16 +31,13 @@ protected WithinFilter(String field, Geometry geometry) { } @Override - protected Set findIndexedIdSet() { - if (getIsFieldIndexed()) { - if (getIndexer() instanceof SpatialIndexer && getValue() != null) { - SpatialIndexer spatialIndexer = (SpatialIndexer) getIndexer(); - RecordStream idSet = spatialIndexer.findWithin(getCollectionName(), getField(), getValue()); - return idSet.toSet(); - } else { - throw new FilterException(getValue() + " is not a Geometry"); - } - } - return new LinkedHashSet<>(); + public List applyOnIndex(IndexMap indexMap) { + // calculated from SpatialIndex + return null; + } + + @Override + public String toString() { + return "(" + getField() + " within " + getValue() + ")"; } } diff --git a/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/mapper/GeometryExtension.java b/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/mapper/GeometryExtension.java index e9528391b..23a7b7c51 100644 --- a/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/mapper/GeometryExtension.java +++ b/nitrite-spatial/src/main/java/org/dizitart/no2/spatial/mapper/GeometryExtension.java @@ -18,7 +18,7 @@ import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.module.SimpleModule; -import org.dizitart.no2.mapper.JacksonExtension; +import org.dizitart.no2.common.mapper.JacksonExtension; import org.locationtech.jts.geom.Geometry; import java.util.List; @@ -38,7 +38,7 @@ public class GeometryExtension implements JacksonExtension { public static final String GEOMETRY_ID = "geometry:"; @Override - public List> getDataTypes() { + public List> getSupportedTypes() { return listOf(Geometry.class); } diff --git a/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/BaseSpatialTest.java b/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/BaseSpatialTest.java new file mode 100644 index 000000000..1ea4f9dd5 --- /dev/null +++ b/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/BaseSpatialTest.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.spatial; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.locationtech.jts.io.ParseException; +import org.locationtech.jts.io.WKTReader; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.common.Constants.*; +import static org.dizitart.no2.spatial.TestUtil.*; + +/** + * @author Anindya Chatterjee + */ +public abstract class BaseSpatialTest { + private String fileName; + protected Nitrite db; + protected NitriteCollection collection; + protected ObjectRepository repository; + protected SpatialData object1, object2, object3; + protected Document doc1, doc2, doc3; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void before() throws ParseException { + fileName = getRandomTempDbFile(); + db = createDb(fileName); + + collection = db.getCollection("test"); + repository = db.getRepository(SpatialData.class); + insertObjects(); + insertDocuments(); + } + + protected void insertObjects() throws ParseException { + WKTReader reader = new WKTReader(); + + object1 = new SpatialData(); + object1.setGeometry(reader.read("POINT(500 505)")); + object1.setId(1L); + repository.insert(object1); + + object2 = new SpatialData(); + object2.setGeometry(reader.read("LINESTRING(550 551, 525 512, 565 566)")); + object2.setId(2L); + repository.insert(object2); + + object3 = new SpatialData(); + object3.setGeometry(reader.read("POLYGON ((550 521, 580 540, 570 564, 512 566, 550 521))")); + object3.setId(3L); + repository.insert(object3); + } + + protected void insertDocuments() throws ParseException { + WKTReader reader = new WKTReader(); + + doc1 = createDocument("key", 1L) + .put("location", reader.read("POINT(500 505)")); + collection.insert(doc1); + + doc2 = createDocument("key", 2L) + .put("location", reader.read("LINESTRING(550 551, 525 512, 565 566)")); + collection.insert(doc2); + + doc3 = createDocument("key", 3L) + .put("location", reader.read("POLYGON ((550 521, 580 540, 570 564, 512 566, 550 521))")); + collection.insert(doc3); + } + + @After + public void after() { + if (db != null && !db.isClosed()) { + db.close(); + } + + deleteDb(fileName); + } + + protected Document trimMeta(Document document) { + document.remove(DOC_ID); + document.remove(DOC_REVISION); + document.remove(DOC_MODIFIED); + document.remove(DOC_SOURCE); + return document; + } +} diff --git a/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/Retry.java b/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/Retry.java new file mode 100644 index 000000000..97691f917 --- /dev/null +++ b/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/Retry.java @@ -0,0 +1,42 @@ +package org.dizitart.no2.spatial; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * @author Anindya Chatterjee + */ +public class Retry implements TestRule { + private final int retryCount; + + public Retry(int retryCount) { + this.retryCount = retryCount; + } + + public Statement apply(Statement base, Description description) { + return statement(base, description); + } + + private Statement statement(final Statement base, final Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + Throwable caughtThrowable = null; + + // implement retry logic here + for (int i = 0; i < retryCount; i++) { + try { + base.evaluate(); + return; + } catch (Throwable t) { + caughtThrowable = t; + System.err.println(description.getDisplayName() + ": run " + (i + 1) + " failed"); + } + } + System.err.println(description.getDisplayName() + ": giving up after " + retryCount + " failures"); + throw caughtThrowable; + } + }; + } +} diff --git a/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/test/SpatialData.java b/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/SpatialData.java similarity index 85% rename from nitrite-spatial/src/test/java/org/dizitart/no2/spatial/test/SpatialData.java rename to nitrite-spatial/src/test/java/org/dizitart/no2/spatial/SpatialData.java index 9bf5f3c72..620fc2874 100644 --- a/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/test/SpatialData.java +++ b/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/SpatialData.java @@ -14,20 +14,20 @@ * limitations under the License. */ -package org.dizitart.no2.spatial.test; +package org.dizitart.no2.spatial; import lombok.Data; import org.dizitart.no2.repository.annotations.Id; import org.dizitart.no2.repository.annotations.Index; import org.locationtech.jts.geom.Geometry; -import static org.dizitart.no2.spatial.SpatialIndexer.SpatialIndex; +import static org.dizitart.no2.spatial.SpatialIndexer.SPATIAL_INDEX; /** * @author Anindya Chatterjee */ @Data -@Index(value = "geometry", type = SpatialIndex) +@Index(value = "geometry", type = SPATIAL_INDEX) public class SpatialData { @Id private Long id; diff --git a/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/SpatialIndexNegativeTest.java b/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/SpatialIndexNegativeTest.java new file mode 100644 index 000000000..6b7439b2f --- /dev/null +++ b/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/SpatialIndexNegativeTest.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.spatial; + +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.filters.FluentFilter; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.repository.Cursor; +import org.junit.Test; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.io.ParseException; +import org.locationtech.jts.io.WKTReader; + +import java.util.Arrays; +import java.util.Collections; +import java.util.stream.Collectors; + +import static org.dizitart.no2.filters.Filter.and; +import static org.dizitart.no2.spatial.FluentFilter.where; +import static org.dizitart.no2.spatial.SpatialIndexer.SPATIAL_INDEX; +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee + */ +public class SpatialIndexNegativeTest extends BaseSpatialTest { + + @Test(expected = FilterException.class) + public void testNoIndex() throws ParseException { + WKTReader reader = new WKTReader(); + Geometry search = reader.read("POLYGON ((490 490, 536 490, 536 515, 490 515, 490 490))"); + + DocumentCursor cursor = collection.find(where("location").intersects(search)); + assertEquals(cursor.size(), 2); + assertEquals(cursor.toList(), Arrays.asList(doc1, doc2)); + } + + @Test(expected = IndexingException.class) + public void testIndexExists() { + collection.createIndex(IndexOptions.indexOptions(SPATIAL_INDEX), "location"); + collection.createIndex(IndexOptions.indexOptions(SPATIAL_INDEX), "location"); + } + + @Test(expected = FilterException.class) + public void testDropIndex() throws ParseException { + repository.dropIndex("geometry"); + WKTReader reader = new WKTReader(); + Geometry search = reader.read("POLYGON ((490 490, 536 490, 536 515, 490 515, 490 490))"); + Cursor cursor = repository.find(where("geometry").within(search)); + assertEquals(cursor.size(), 1); + } + + @Test(expected = FilterException.class) + public void testFindEqual() throws ParseException { + WKTReader reader = new WKTReader(); + Geometry search = reader.read("POINT(500 505)"); + + Cursor cursor = repository.find(FluentFilter.where("geometry").eq(search)); + assertEquals(cursor.size(), 2); + assertEquals(cursor.toList(), Collections.singletonList(object1)); + } + + @Test(expected = IndexingException.class) + public void testCompoundIndex() throws ParseException { + WKTReader reader = new WKTReader(); + Geometry search = reader.read("POLYGON ((490 490, 536 490, 536 515, 490 515, 490 490))"); + + collection.createIndex(IndexOptions.indexOptions(SPATIAL_INDEX), "location", "key"); + DocumentCursor cursor1 = collection.find(where("location").intersects(search)); + assertEquals(cursor1.size(), 2); + assertEquals(cursor1.toList() + .stream() + .map(this::trimMeta) + .collect(Collectors.toList()), Arrays.asList(doc1, doc2)); + } + + @Test(expected = FilterException.class) + public void testMultipleSpatialIndexOnMultipleFields() throws ParseException { + WKTReader reader = new WKTReader(); + Geometry search = reader.read("POLYGON ((490 490, 536 490, 536 515, 490 515, 490 490))"); + + collection.createIndex(IndexOptions.indexOptions(SPATIAL_INDEX), "location"); + collection.createIndex(IndexOptions.indexOptions(SPATIAL_INDEX), "area"); + + DocumentCursor cursor = collection.find( + and( + where("location").intersects(search), + where("area").within(search) + ) + ); + assertEquals(0, cursor.size()); + } +} diff --git a/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/SpatialIndexTest.java b/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/SpatialIndexTest.java new file mode 100644 index 000000000..3d8c14d64 --- /dev/null +++ b/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/SpatialIndexTest.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2017-2020. Nitrite author or authors. + * + * Licensed 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.dizitart.no2.spatial; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.filters.EqualsFilter; +import org.dizitart.no2.filters.FluentFilter; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.mvstore.MVStoreModule; +import org.dizitart.no2.repository.Cursor; +import org.junit.Test; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.geom.Point; +import org.locationtech.jts.io.ParseException; +import org.locationtech.jts.io.WKTReader; + +import java.util.Arrays; +import java.util.Collections; +import java.util.stream.Collectors; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.Filter.and; +import static org.dizitart.no2.index.IndexType.UNIQUE; +import static org.dizitart.no2.spatial.FluentFilter.where; +import static org.dizitart.no2.spatial.SpatialIndexer.SPATIAL_INDEX; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class SpatialIndexTest extends BaseSpatialTest { + + @Test + public void testIntersect() throws ParseException { + WKTReader reader = new WKTReader(); + Geometry search = reader.read("POLYGON ((490 490, 536 490, 536 515, 490 515, 490 490))"); + + Cursor cursor = repository.find(where("geometry").intersects(search)); + assertEquals(cursor.size(), 2); + assertEquals(cursor.toList(), Arrays.asList(object1, object2)); + + collection.createIndex(IndexOptions.indexOptions(SPATIAL_INDEX), "location"); + DocumentCursor cursor1 = collection.find(where("location").intersects(search)); + assertEquals(cursor1.size(), 2); + assertEquals(cursor1.toList().stream().map(this::trimMeta).collect(Collectors.toList()), Arrays.asList(doc1, doc2)); + } + + @Test + public void testWithin() throws ParseException { + WKTReader reader = new WKTReader(); + Geometry search = reader.read("POLYGON ((490 490, 536 490, 536 515, 490 515, 490 490))"); + + Cursor cursor = repository.find(where("geometry").within(search)); + assertEquals(cursor.size(), 1); + assertEquals(cursor.toList(), Collections.singletonList(object1)); + + collection.createIndex(IndexOptions.indexOptions(SPATIAL_INDEX), "location"); + DocumentCursor cursor1 = collection.find(where("location").within(search)); + assertEquals(cursor1.size(), 1); + assertEquals(cursor1.toList().stream().map(this::trimMeta).collect(Collectors.toList()), Collections.singletonList(doc1)); + } + + @Test + public void testNearPoint() throws ParseException { + WKTReader reader = new WKTReader(); + Point search = (Point) reader.read("POINT (490 490)"); + + Cursor cursor = repository.find(where("geometry").near(search, 20.0)); + assertEquals(cursor.size(), 1); + assertEquals(cursor.toList(), Collections.singletonList(object1)); + + collection.createIndex(IndexOptions.indexOptions(SPATIAL_INDEX), "location"); + DocumentCursor cursor1 = collection.find(where("location").near(search, 20.0)); + assertEquals(cursor1.size(), 1); + assertEquals(cursor1.toList().stream().map(this::trimMeta).collect(Collectors.toList()), Collections.singletonList(doc1)); + } + + @Test + public void testNearCoordinate() throws ParseException { + WKTReader reader = new WKTReader(); + Point search = (Point) reader.read("POINT (490 490)"); + Coordinate coordinate = search.getCoordinate(); + + Cursor cursor = repository.find(where("geometry").near(coordinate, 20.0)); + assertEquals(cursor.size(), 1); + assertEquals(cursor.toList(), Collections.singletonList(object1)); + + collection.createIndex(IndexOptions.indexOptions(SPATIAL_INDEX), "location"); + DocumentCursor cursor1 = collection.find(where("location").near(coordinate, 20.0)); + assertEquals(cursor1.size(), 1); + assertEquals(cursor1.toList().stream().map(this::trimMeta).collect(Collectors.toList()), Collections.singletonList(doc1)); + } + + @Test + public void testRemoveIndexEntry() throws ParseException { + WKTReader reader = new WKTReader(); + Geometry search = reader.read("POLYGON ((490 490, 536 490, 536 515, 490 515, 490 490))"); + WriteResult result = repository.remove(where("geometry").within(search)); + assertEquals(result.getAffectedCount(), 1); + } + + @Test + public void testUpdateIndex() throws ParseException { + WKTReader reader = new WKTReader(); + Geometry search = reader.read("POLYGON ((490 490, 536 490, 536 515, 490 515, 490 490))"); + SpatialData update = new SpatialData(); + update.setId(3L); + update.setGeometry(search); + + WriteResult result = repository.update(update); + assertEquals(result.getAffectedCount(), 1); + } + + @Test + public void testDropAllIndex() { + repository.dropAllIndices(); + + assertFalse(repository.hasIndex("geometry")); + } + + @Test + public void testParseGeometry() throws ParseException { + MVStoreModule storeModule = MVStoreModule.withConfig() + .filePath((String) null) + .build(); + + db = Nitrite.builder() + .loadModule(storeModule) + .loadModule(new SpatialModule()) + .fieldSeparator(".") + .openOrCreate(); + + WKTReader reader = new WKTReader(); + Geometry point = reader.read("POINT(500 505)"); + Document document = createDocument("geom", point); + + NitriteCollection collection = db.getCollection("test"); + collection.insert(document); + collection.createIndex(IndexOptions.indexOptions(SPATIAL_INDEX), "geom"); + Document doc = collection.find().firstOrNull(); + + Document update = doc.clone(); + update.put("geom", reader.read("POINT(0 0)")); + collection.update(update); + } + + @Test + public void testAndMixedQuery() throws ParseException { + WKTReader reader = new WKTReader(); + Geometry search = reader.read("POLYGON ((490 490, 536 490, 536 515, 490 515, 490 490))"); + + collection.createIndex(IndexOptions.indexOptions(UNIQUE), "key"); + collection.createIndex(IndexOptions.indexOptions(SPATIAL_INDEX), "location"); + DocumentCursor cursor = collection.find( + and( + where("location").intersects(search), + FluentFilter.where("key").eq(2L) + ) + ); + + FindPlan findPlan = cursor.getFindPlan(); + assertEquals(1, findPlan.getIndexScanFilter().getFilters().size()); + assertTrue(findPlan.getIndexScanFilter().getFilters().get(0) instanceof IntersectsFilter); + assertTrue(findPlan.getCollectionScanFilter() instanceof EqualsFilter); + + assertEquals(cursor.size(), 1); + assertEquals(cursor.toList() + .stream() + .map(this::trimMeta) + .collect(Collectors.toList()), Collections.singletonList(doc2)); + } + @Test + public void testAndSpatialQuery() throws ParseException { + WKTReader reader = new WKTReader(); + Geometry search = reader.read("POLYGON ((490 490, 536 490, 536 515, 490 515, 490 490))"); + + collection.createIndex(IndexOptions.indexOptions(SPATIAL_INDEX), "location"); + DocumentCursor cursor = collection.find( + and( + where("location").intersects(search), + where("location").within(search) + ) + ); + + assertEquals(cursor.size(), 2); + assertEquals(cursor.toList() + .stream() + .map(this::trimMeta) + .collect(Collectors.toList()), Arrays.asList(doc1, doc2)); + } +} diff --git a/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/SpatialViewer.java b/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/SpatialViewer.java new file mode 100644 index 000000000..0893b2180 --- /dev/null +++ b/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/SpatialViewer.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.spatial; + +import org.locationtech.jts.awt.ShapeWriter; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.io.WKTReader; + +import javax.swing.*; +import java.awt.*; + +/** + * @author Anindya Chatterjee + */ +public class SpatialViewer { + public static void main(String[] args) { + JFrame f = new JFrame(); + f.getContentPane().add(new Paint()); + f.setSize(700, 700); + f.setVisible(true); + f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + } + + public static class Paint extends JPanel { + + public void paint(Graphics g) { + try { + Graphics2D g2d = (Graphics2D) g; + RenderingHints rh = new RenderingHints( + RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + rh.put(RenderingHints.KEY_RENDERING, + RenderingHints.VALUE_RENDER_QUALITY); + + g2d.setRenderingHints(rh); + + + WKTReader reader = new WKTReader(); + Geometry point = reader.read("POINT(500 505)"); + Geometry point2 = reader.read("POINT (490 490)"); + Geometry line = reader.read("LINESTRING(550 551, 525 512, 565 566)"); + Geometry polygon = reader.read("POLYGON ((550 521, 580 540, 570 564, 512 566, 550 521))"); + Geometry search = reader.read("POLYGON ((490 490, 536 490, 536 515, 490 515, 490 490))"); + + + ShapeWriter sw = new ShapeWriter(); + Shape pointShape = sw.toShape(point); + Shape pointShape2 = sw.toShape(point2); + Shape lineShape = sw.toShape(line); + Shape polygonShape = sw.toShape(polygon); + Shape searchShape = sw.toShape(search); + + g2d.setColor(Color.RED); + g2d.draw(pointShape); + g2d.draw(pointShape2); + g2d.draw(lineShape); + g2d.draw(polygonShape); + + g2d.setColor(Color.GREEN); + g2d.draw(searchShape); + + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} diff --git a/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/TestUtil.java b/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/TestUtil.java new file mode 100644 index 000000000..99b0526f5 --- /dev/null +++ b/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/TestUtil.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.spatial; + +import lombok.SneakyThrows; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.common.mapper.JacksonMapperModule; +import org.dizitart.no2.mvstore.MVStoreModule; +import org.dizitart.no2.spatial.mapper.GeometryExtension; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.UUID; + +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee + */ +public class TestUtil { + public static String getRandomTempDbFile() { + String dataDir = System.getProperty("java.io.tmpdir") + File.separator + "nitrite" + File.separator + "data"; + File file = new File(dataDir); + if (!file.exists()) { + assertTrue(file.mkdirs()); + } + return file.getPath() + File.separator + UUID.randomUUID() + ".db"; + } + + public static Nitrite createDb(String fileName) { + MVStoreModule module = MVStoreModule.withConfig() + .filePath(fileName) + .build(); + + return Nitrite.builder() + .loadModule(module) + .loadModule(new JacksonMapperModule(new GeometryExtension())) + .loadModule(new SpatialModule()) + .fieldSeparator(".") + .openOrCreate(); + } + + @SneakyThrows + public static void deleteDb(String fileName) { + Files.delete(Paths.get(fileName)); + } +} diff --git a/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/test/Retry.java b/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/test/Retry.java deleted file mode 100644 index eb978cb53..000000000 --- a/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/test/Retry.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.dizitart.no2.spatial.test; - -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; - -/** - * @author Anindya Chatterjee - */ -public class Retry implements TestRule { - private final int retryCount; - - public Retry(int retryCount) { - this.retryCount = retryCount; - } - - public Statement apply(Statement base, Description description) { - return statement(base, description); - } - - private Statement statement(final Statement base, final Description description) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - Throwable caughtThrowable = null; - - // implement retry logic here - for (int i = 0; i < retryCount; i++) { - try { - base.evaluate(); - return; - } catch (Throwable t) { - caughtThrowable = t; - System.err.println(description.getDisplayName() + ": run " + (i + 1) + " failed"); - } - } - System.err.println(description.getDisplayName() + ": giving up after " + retryCount + " failures"); - throw caughtThrowable; - } - }; - } -} diff --git a/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/test/SpatialIndexTest.java b/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/test/SpatialIndexTest.java deleted file mode 100644 index c0016860d..000000000 --- a/nitrite-spatial/src/test/java/org/dizitart/no2/spatial/test/SpatialIndexTest.java +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.spatial.test; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.exceptions.IndexingException; -import org.dizitart.no2.filters.FluentFilter; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.mapper.JacksonMapperModule; -import org.dizitart.no2.mvstore.MVStoreModule; -import org.dizitart.no2.repository.Cursor; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.spatial.SpatialModule; -import org.dizitart.no2.spatial.mapper.GeometryExtension; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.locationtech.jts.awt.ShapeWriter; -import org.locationtech.jts.geom.Coordinate; -import org.locationtech.jts.geom.Geometry; -import org.locationtech.jts.geom.Point; -import org.locationtech.jts.io.ParseException; -import org.locationtech.jts.io.WKTReader; - -import javax.swing.*; -import java.awt.*; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Collections; -import java.util.UUID; -import java.util.stream.Collectors; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.common.Constants.*; -import static org.dizitart.no2.spatial.FluentFilter.where; -import static org.dizitart.no2.spatial.SpatialIndexer.SpatialIndex; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -public class SpatialIndexTest { - private final String fileName = getRandomTempDbFile(); - private Nitrite db; - private NitriteCollection collection; - private ObjectRepository repository; - private SpatialData object1, object2, object3; - private Document doc1, doc2, doc3; - - @Rule - public Retry retry = new Retry(3); - - public static void main(String[] args) { - JFrame f = new JFrame(); - f.getContentPane().add(new Paint()); - f.setSize(700, 700); - f.setVisible(true); - f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - } - - public static String getRandomTempDbFile() { - String dataDir = System.getProperty("java.io.tmpdir") + File.separator + "nitrite" + File.separator + "data"; - File file = new File(dataDir); - if (!file.exists()) { - assertTrue(file.mkdirs()); - } - return file.getPath() + File.separator + UUID.randomUUID().toString() + ".db"; - } - - @Before - public void before() throws ParseException { - MVStoreModule module = MVStoreModule.withConfig() - .filePath(fileName) - .build(); - - db = Nitrite.builder() - .loadModule(module) - .loadModule(new JacksonMapperModule(new GeometryExtension())) - .loadModule(new SpatialModule()) - .fieldSeparator(".") - .openOrCreate(); - - collection = db.getCollection("test"); - repository = db.getRepository(SpatialData.class); - insertObjects(); - insertDocuments(); - } - - protected void insertObjects() throws ParseException { - WKTReader reader = new WKTReader(); - - object1 = new SpatialData(); - object1.setGeometry(reader.read("POINT(500 505)")); - object1.setId(1L); - repository.insert(object1); - - object2 = new SpatialData(); - object2.setGeometry(reader.read("LINESTRING(550 551, 525 512, 565 566)")); - object2.setId(2L); - repository.insert(object2); - - object3 = new SpatialData(); - object3.setGeometry(reader.read("POLYGON ((550 521, 580 540, 570 564, 512 566, 550 521))")); - object3.setId(3L); - repository.insert(object3); - } - - protected void insertDocuments() throws ParseException { - WKTReader reader = new WKTReader(); - - doc1 = createDocument("key", 1L) - .put("location", reader.read("POINT(500 505)")); - collection.insert(doc1); - - doc2 = createDocument("key", 2L) - .put("location", reader.read("LINESTRING(550 551, 525 512, 565 566)")); - collection.insert(doc2); - - doc3 = createDocument("key", 3L) - .put("location", reader.read("POLYGON ((550 521, 580 540, 570 564, 512 566, 550 521))")); - collection.insert(doc3); - } - - @After - public void after() throws IOException { - if (db != null && !db.isClosed()) { - db.close(); - } - - Files.delete(Paths.get(fileName)); - } - - @Test - public void testIntersect() throws ParseException { - WKTReader reader = new WKTReader(); - Geometry search = reader.read("POLYGON ((490 490, 536 490, 536 515, 490 515, 490 490))"); - - Cursor cursor = repository.find(where("geometry").intersects(search)); - assertEquals(cursor.size(), 2); - assertEquals(cursor.toList(), Arrays.asList(object1, object2)); - - collection.createIndex("location", IndexOptions.indexOptions(SpatialIndex)); - DocumentCursor cursor1 = collection.find(where("location").intersects(search)); - assertEquals(cursor1.size(), 2); - assertEquals(cursor1.toList().stream().map(this::trimMeta).collect(Collectors.toList()), Arrays.asList(doc1, doc2)); - } - - @Test - public void testWithin() throws ParseException { - WKTReader reader = new WKTReader(); - Geometry search = reader.read("POLYGON ((490 490, 536 490, 536 515, 490 515, 490 490))"); - - Cursor cursor = repository.find(where("geometry").within(search)); - assertEquals(cursor.size(), 1); - assertEquals(cursor.toList(), Collections.singletonList(object1)); - - collection.createIndex("location", IndexOptions.indexOptions(SpatialIndex)); - DocumentCursor cursor1 = collection.find(where("location").within(search)); - assertEquals(cursor1.size(), 1); - assertEquals(cursor1.toList().stream().map(this::trimMeta).collect(Collectors.toList()), Collections.singletonList(doc1)); - } - - @Test - public void testNearPoint() throws ParseException { - WKTReader reader = new WKTReader(); - Point search = (Point) reader.read("POINT (490 490)"); - - Cursor cursor = repository.find(where("geometry").near(search, 20.0)); - assertEquals(cursor.size(), 1); - assertEquals(cursor.toList(), Collections.singletonList(object1)); - - collection.createIndex("location", IndexOptions.indexOptions(SpatialIndex)); - DocumentCursor cursor1 = collection.find(where("location").near(search, 20.0)); - assertEquals(cursor1.size(), 1); - assertEquals(cursor1.toList().stream().map(this::trimMeta).collect(Collectors.toList()), Collections.singletonList(doc1)); - } - - @Test - public void testNearCoordinate() throws ParseException { - WKTReader reader = new WKTReader(); - Point search = (Point) reader.read("POINT (490 490)"); - Coordinate coordinate = search.getCoordinate(); - - Cursor cursor = repository.find(where("geometry").near(coordinate, 20.0)); - assertEquals(cursor.size(), 1); - assertEquals(cursor.toList(), Collections.singletonList(object1)); - - collection.createIndex("location", IndexOptions.indexOptions(SpatialIndex)); - DocumentCursor cursor1 = collection.find(where("location").near(coordinate, 20.0)); - assertEquals(cursor1.size(), 1); - assertEquals(cursor1.toList().stream().map(this::trimMeta).collect(Collectors.toList()), Collections.singletonList(doc1)); - } - - @Test(expected = FilterException.class) - public void testNoIndex() throws ParseException { - WKTReader reader = new WKTReader(); - Geometry search = reader.read("POLYGON ((490 490, 536 490, 536 515, 490 515, 490 490))"); - - DocumentCursor cursor1 = collection.find(where("location").intersects(search)); - assertEquals(cursor1.size(), 2); - assertEquals(cursor1.toList(), Arrays.asList(doc1, doc2)); - } - - @Test(expected = IndexingException.class) - public void testIndexExists() { - collection.createIndex("location", IndexOptions.indexOptions(SpatialIndex)); - collection.createIndex("location", IndexOptions.indexOptions(SpatialIndex)); - } - - @Test - public void testRemoveIndexEntry() throws ParseException { - WKTReader reader = new WKTReader(); - Geometry search = reader.read("POLYGON ((490 490, 536 490, 536 515, 490 515, 490 490))"); - WriteResult result = repository.remove(where("geometry").within(search)); - assertEquals(result.getAffectedCount(), 1); - } - - @Test - public void testUpdateIndex() throws ParseException { - WKTReader reader = new WKTReader(); - Geometry search = reader.read("POLYGON ((490 490, 536 490, 536 515, 490 515, 490 490))"); - SpatialData update = new SpatialData(); - update.setId(3L); - update.setGeometry(search); - - WriteResult result = repository.update(update); - assertEquals(result.getAffectedCount(), 1); - } - - @Test(expected = FilterException.class) - public void testDropIndex() throws ParseException { - repository.dropIndex("geometry"); - WKTReader reader = new WKTReader(); - Geometry search = reader.read("POLYGON ((490 490, 536 490, 536 515, 490 515, 490 490))"); - Cursor cursor = repository.find(where("geometry").within(search)); - assertEquals(cursor.size(), 1); - } - - @Test - public void testDropAllIndex() { - repository.dropAllIndices(); - - assertFalse(repository.hasIndex("geometry")); - } - - @Test(expected = FilterException.class) - public void testFindEqual() throws ParseException { - WKTReader reader = new WKTReader(); - Geometry search = reader.read("POINT(500 505)"); - - Cursor cursor = repository.find(FluentFilter.where("geometry").eq(search)); - assertEquals(cursor.size(), 2); - assertEquals(cursor.toList(), Collections.singletonList(object1)); - } - - @Test - public void testParseGeometry() throws ParseException { - MVStoreModule storeModule = MVStoreModule.withConfig() - .filePath((String) null) - .build(); - - db = Nitrite.builder() - .loadModule(storeModule) - .loadModule(new SpatialModule()) - .fieldSeparator(".") - .openOrCreate(); - - WKTReader reader = new WKTReader(); - Geometry point = reader.read("POINT(500 505)"); - Document document = createDocument("geom", point); - - NitriteCollection collection = db.getCollection("test"); - collection.insert(document); - collection.createIndex("geom", IndexOptions.indexOptions(SpatialIndex)); - Document doc = collection.find().firstOrNull(); - - Document update = doc.clone(); - update.put("geom", reader.read("POINT(0 0)")); - collection.update(update); - } - - private Document trimMeta(Document document) { - document.remove(DOC_ID); - document.remove(DOC_REVISION); - document.remove(DOC_MODIFIED); - document.remove(DOC_SOURCE); - return document; - } - - public static class Paint extends JPanel { - - public void paint(Graphics g) { - try { - Graphics2D g2d = (Graphics2D) g; - RenderingHints rh = new RenderingHints( - RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_ON); - - rh.put(RenderingHints.KEY_RENDERING, - RenderingHints.VALUE_RENDER_QUALITY); - - g2d.setRenderingHints(rh); - - - WKTReader reader = new WKTReader(); - Geometry point = reader.read("POINT(500 505)"); - Geometry point2 = reader.read("POINT (490 490)"); - Geometry line = reader.read("LINESTRING(550 551, 525 512, 565 566)"); - Geometry polygon = reader.read("POLYGON ((550 521, 580 540, 570 564, 512 566, 550 521))"); - Geometry search = reader.read("POLYGON ((490 490, 536 490, 536 515, 490 515, 490 490))"); - - - ShapeWriter sw = new ShapeWriter(); - Shape pointShape = sw.toShape(point); - Shape pointShape2 = sw.toShape(point2); - Shape lineShape = sw.toShape(line); - Shape polygonShape = sw.toShape(polygon); - Shape searchShape = sw.toShape(search); - - g2d.setColor(Color.RED); - g2d.draw(pointShape); - g2d.draw(pointShape2); - g2d.draw(lineShape); - g2d.draw(polygonShape); - - g2d.setColor(Color.GREEN); - g2d.draw(searchShape); - - } catch (Exception e) { - e.printStackTrace(); - } - } - } -} diff --git a/nitrite-support/src/main/java/org/dizitart/no2/support/NitriteJsonExporter.java b/nitrite-support/src/main/java/org/dizitart/no2/support/NitriteJsonExporter.java index 67dec708e..cb2fcff73 100644 --- a/nitrite-support/src/main/java/org/dizitart/no2/support/NitriteJsonExporter.java +++ b/nitrite-support/src/main/java/org/dizitart/no2/support/NitriteJsonExporter.java @@ -24,7 +24,7 @@ import org.dizitart.no2.collection.NitriteCollection; import org.dizitart.no2.common.PersistentCollection; import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.index.IndexEntry; +import org.dizitart.no2.index.IndexDescriptor; import org.dizitart.no2.repository.ObjectRepository; import java.io.ByteArrayOutputStream; @@ -139,7 +139,7 @@ private void writeRepository(ObjectRepository repository) throws IOException generator.writeFieldName(TAG_TYPE); generator.writeString(repository.getType().getName()); - Collection indices = repository.listIndices(); + Collection indices = repository.listIndices(); writeIndices(indices); DocumentCursor cursor = repository.getDocumentCollection().find(); @@ -156,7 +156,7 @@ private void writeKeyedRepository(String key, ObjectRepository repository) th generator.writeFieldName(TAG_TYPE); generator.writeString(repository.getType().getName()); - Collection indices = repository.listIndices(); + Collection indices = repository.listIndices(); writeIndices(indices); DocumentCursor cursor = repository.getDocumentCollection().find(); @@ -169,7 +169,7 @@ private void writeCollection(NitriteCollection nitriteCollection) throws IOExcep generator.writeFieldName(TAG_NAME); generator.writeString(nitriteCollection.getName()); - Collection indices = nitriteCollection.listIndices(); + Collection indices = nitriteCollection.listIndices(); writeIndices(indices); DocumentCursor cursor = nitriteCollection.find(); @@ -177,11 +177,11 @@ private void writeCollection(NitriteCollection nitriteCollection) throws IOExcep generator.writeEndObject(); } - private void writeIndices(Collection indices) throws IOException { + private void writeIndices(Collection indices) throws IOException { generator.writeFieldName(TAG_INDICES); generator.writeStartArray(); if (options.isExportIndices()) { - for (IndexEntry index : indices) { + for (IndexDescriptor index : indices) { generator.writeStartObject(); generator.writeFieldName(TAG_INDEX); generator.writeObject(writeEncodedObject(index)); diff --git a/nitrite-support/src/main/java/org/dizitart/no2/support/NitriteJsonImporter.java b/nitrite-support/src/main/java/org/dizitart/no2/support/NitriteJsonImporter.java index 2c72576f0..e62526647 100644 --- a/nitrite-support/src/main/java/org/dizitart/no2/support/NitriteJsonImporter.java +++ b/nitrite-support/src/main/java/org/dizitart/no2/support/NitriteJsonImporter.java @@ -24,8 +24,7 @@ import org.dizitart.no2.collection.NitriteCollection; import org.dizitart.no2.common.PersistentCollection; import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.index.IndexEntry; -import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexDescriptor; import org.dizitart.no2.repository.ObjectRepository; import java.io.ByteArrayInputStream; @@ -33,6 +32,7 @@ import java.io.ObjectInputStream; import static org.dizitart.no2.common.Constants.*; +import static org.dizitart.no2.index.IndexOptions.indexOptions; /** * @author Anindya Chatterjee. @@ -179,12 +179,12 @@ private void readIndices(PersistentCollection collection) throws IOException if (TAG_INDEX.equals(fieldName)) { parser.nextToken(); String data = parser.readValueAs(String.class); - IndexEntry index = (IndexEntry) readEncodedObject(data); - if (collection != null && index != null - && index.getField() != null - && !collection.hasIndex(index.getField())) { - collection.createIndex(index.getField(), - IndexOptions.indexOptions(index.getIndexType())); + IndexDescriptor index = (IndexDescriptor) readEncodedObject(data); + if (index != null) { + String[] fieldNames = index.getIndexFields().getFieldNames().toArray(new String[0]); + if (collection != null && index.getIndexFields() != null && !collection.hasIndex(fieldNames)) { + collection.createIndex(indexOptions(index.getIndexType()), fieldNames); + } } } } diff --git a/nitrite-support/src/test/java/org/dizitart/no2/support/Company.java b/nitrite-support/src/test/java/org/dizitart/no2/support/Company.java index 661ac8ac8..b92a9d6fe 100644 --- a/nitrite-support/src/test/java/org/dizitart/no2/support/Company.java +++ b/nitrite-support/src/test/java/org/dizitart/no2/support/Company.java @@ -24,8 +24,8 @@ import org.dizitart.no2.repository.annotations.Id; import org.dizitart.no2.repository.annotations.Index; import org.dizitart.no2.repository.annotations.Indices; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; import java.io.Serializable; import java.util.Date; diff --git a/nitrite-support/src/test/java/org/dizitart/no2/support/Employee.java b/nitrite-support/src/test/java/org/dizitart/no2/support/Employee.java index ad715bdd0..6e97fa636 100644 --- a/nitrite-support/src/test/java/org/dizitart/no2/support/Employee.java +++ b/nitrite-support/src/test/java/org/dizitart/no2/support/Employee.java @@ -25,8 +25,8 @@ import org.dizitart.no2.repository.annotations.Id; import org.dizitart.no2.repository.annotations.Index; import org.dizitart.no2.repository.annotations.Indices; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; import java.io.Serializable; import java.util.Date; @@ -37,9 +37,9 @@ @ToString @EqualsAndHashCode @Indices({ - @Index(value = "joinDate", type = IndexType.NonUnique), - @Index(value = "address", type = IndexType.Fulltext), - @Index(value = "employeeNote.text", type = IndexType.Fulltext) + @Index(value = "joinDate", type = IndexType.NON_UNIQUE), + @Index(value = "address", type = IndexType.FULL_TEXT), + @Index(value = "employeeNote.text", type = IndexType.FULL_TEXT) }) public class Employee implements Serializable, Mappable { @Id diff --git a/nitrite-support/src/test/java/org/dizitart/no2/support/ExporterImporterOptionTest.java b/nitrite-support/src/test/java/org/dizitart/no2/support/ExporterImporterOptionTest.java index f7b868910..1523eff59 100644 --- a/nitrite-support/src/test/java/org/dizitart/no2/support/ExporterImporterOptionTest.java +++ b/nitrite-support/src/test/java/org/dizitart/no2/support/ExporterImporterOptionTest.java @@ -19,7 +19,7 @@ import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.NitriteCollection; import org.dizitart.no2.common.PersistentCollection; -import org.dizitart.no2.index.IndexEntry; +import org.dizitart.no2.index.IndexDescriptor; import org.dizitart.no2.repository.ObjectRepository; import org.junit.Test; @@ -87,6 +87,6 @@ public void testImportExportSingle() { new ArrayList()); assertEquals(destCompRepo.listIndices(), sourceCompRepo.listIndices()); - assertEquals(destSecondColl.listIndices(), new LinkedHashSet()); + assertEquals(destSecondColl.listIndices(), new LinkedHashSet()); } } diff --git a/nitrite-support/src/test/java/org/dizitart/no2/support/Note.java b/nitrite-support/src/test/java/org/dizitart/no2/support/Note.java index 2e6aeb4f5..4f78a970b 100644 --- a/nitrite-support/src/test/java/org/dizitart/no2/support/Note.java +++ b/nitrite-support/src/test/java/org/dizitart/no2/support/Note.java @@ -20,8 +20,8 @@ import lombok.Getter; import lombok.Setter; import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; import java.io.Serializable; diff --git a/nitrite/build.gradle b/nitrite/build.gradle index 87bbdf04c..00d1e7b4d 100644 --- a/nitrite/build.gradle +++ b/nitrite/build.gradle @@ -50,6 +50,7 @@ dependencies { testAnnotationProcessor "org.projectlombok:lombok:1.18.12" testImplementation "junit:junit:4.13.1" + testImplementation "org.mockito:mockito-core:3.9.0" testImplementation "uk.co.jemos.podam:podam:7.2.5.RELEASE" testImplementation "com.github.javafaker:javafaker:1.0.2" testImplementation "org.apache.lucene:lucene-core:8.6.3" diff --git a/nitrite/src/main/java/org/dizitart/no2/Nitrite.java b/nitrite/src/main/java/org/dizitart/no2/Nitrite.java index 3a1bd9429..4c4cf5e3d 100644 --- a/nitrite/src/main/java/org/dizitart/no2/Nitrite.java +++ b/nitrite/src/main/java/org/dizitart/no2/Nitrite.java @@ -21,11 +21,10 @@ import org.dizitart.no2.exceptions.NitriteIOException; import org.dizitart.no2.exceptions.ValidationException; import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.store.DatabaseMetaData; +import org.dizitart.no2.store.StoreMetaData; import org.dizitart.no2.store.NitriteStore; import org.dizitart.no2.transaction.Session; -import java.io.Closeable; import java.util.Map; import java.util.Set; @@ -40,19 +39,19 @@ * @author Anindya Chatterjee * @since 1.0 */ -public interface Nitrite extends Closeable { +public interface Nitrite extends AutoCloseable { + /** + * Returns an instance of a {@link NitriteBuilder}. + * + * @return the nitrite builder + */ static NitriteBuilder builder() { return new NitriteBuilder(); } /** - * Closes the database. Unsaved changes are written to disk for a file based store. - */ - void close(); - - /** - * Commits the changes. For file based store, it saves the changes + * Commits the unsaved changes. For file based store, it saves the changes * to disk if there are any unsaved changes. *

* No need to call it after every change, if auto-commit is not disabled @@ -113,6 +112,30 @@ static NitriteBuilder builder() { */ ObjectRepository getRepository(Class type, String key); + /** + * Destroys a collection without opening the {@link NitriteCollection} first. + * + * @param name the name of the collection + */ + void destroyCollection(String name); + + /** + * Destroys an {@link ObjectRepository} without opening it first. + * + * @param the type parameter + * @param type the type + */ + void destroyRepository(Class type); + + /** + * Destroys an {@link ObjectRepository} without opening it first. + * + * @param the type parameter + * @param type the type + * @param key the key + */ + void destroyRepository(Class type, String key); + /** * Gets the set of all {@link NitriteCollection}s' names saved in the store. * @@ -139,14 +162,14 @@ static NitriteBuilder builder() { /** * Checks whether the store has any unsaved changes. * - * @return `true` if there are unsaved changes; otherwise `false`. + * @return true if there are unsaved changes; otherwise false. */ boolean hasUnsavedChanges(); /** * Checks whether the store is closed. * - * @return `true` if closed; otherwise `false`. + * @return true if closed; otherwise false. */ boolean isClosed(); @@ -169,8 +192,7 @@ static NitriteBuilder builder() { * * @return the database meta data */ - DatabaseMetaData getDatabaseMetaData(); - + StoreMetaData getDatabaseMetaData(); /** * Creates a {@link Session} for transaction. @@ -179,11 +201,16 @@ static NitriteBuilder builder() { */ Session createSession(); + /** + * Closes the database. + * */ + void close(); + /** * Checks whether a particular {@link NitriteCollection} exists in the store. * * @param name the name of the collection. - * @return `true` if the collection exists; otherwise `false`. + * @return true if the collection exists; otherwise false. */ default boolean hasCollection(String name) { checkOpened(); @@ -195,7 +222,7 @@ default boolean hasCollection(String name) { * * @param the type parameter * @param type the type of the object - * @return `true` if the repository exists; otherwise `false`. + * @return true if the repository exists; otherwise false. */ default boolean hasRepository(Class type) { checkOpened(); @@ -206,9 +233,9 @@ default boolean hasRepository(Class type) { * Checks whether a particular keyed-{@link ObjectRepository} exists in the store. * * @param the type parameter. - * @param key the key, which will be appended to the repositories name. * @param type the type of the object. - * @return `true` if the repository exists; otherwise `false`. + * @param key the key, which will be appended to the repositories name. + * @return true if the repository exists; otherwise false. */ default boolean hasRepository(Class type, String key) { checkOpened(); @@ -216,6 +243,11 @@ default boolean hasRepository(Class type, String key) { && listKeyedRepository().get(key).contains(type.getName()); } + /** + * Validate the collection name. + * + * @param name the name + */ default void validateCollectionName(String name) { notNull(name, "name cannot be null"); notEmpty(name, "name cannot be empty"); @@ -227,6 +259,9 @@ default void validateCollectionName(String name) { } } + /** + * Checks if the store is opened. + */ default void checkOpened() { if (getStore() == null || getStore().isClosed()) { throw new NitriteIOException("store is closed"); diff --git a/nitrite/src/main/java/org/dizitart/no2/NitriteBuilder.java b/nitrite/src/main/java/org/dizitart/no2/NitriteBuilder.java index 68de2b89a..8262ba811 100644 --- a/nitrite/src/main/java/org/dizitart/no2/NitriteBuilder.java +++ b/nitrite/src/main/java/org/dizitart/no2/NitriteBuilder.java @@ -19,9 +19,9 @@ import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.dizitart.no2.common.concurrent.ThreadPoolManager; -import org.dizitart.no2.exceptions.SecurityException; +import org.dizitart.no2.exceptions.NitriteSecurityException; import org.dizitart.no2.migration.Migration; -import org.dizitart.no2.module.NitriteModule; +import org.dizitart.no2.common.module.NitriteModule; /** * A builder utility to create a {@link Nitrite} database instance. @@ -35,6 +35,9 @@ public class NitriteBuilder { @Getter private final NitriteConfig nitriteConfig; + /** + * Instantiates a new {@link NitriteBuilder}. + */ NitriteBuilder() { this.nitriteConfig = new NitriteConfig(); } @@ -62,6 +65,12 @@ public NitriteBuilder loadModule(NitriteModule module) { return this; } + /** + * Adds instructions to perform during schema migration. + * + * @param migrations the migrations + * @return the nitrite builder + */ public NitriteBuilder addMigrations(Migration... migrations) { for (Migration migration : migrations) { this.nitriteConfig.addMigration(migration); @@ -69,6 +78,12 @@ public NitriteBuilder addMigrations(Migration... migrations) { return this; } + /** + * Sets the current schema version. + * + * @param version the version + * @return the nitrite builder + */ public NitriteBuilder schemaVersion(Integer version) { this.nitriteConfig.schemaVersion(version); return this; @@ -80,9 +95,8 @@ public NitriteBuilder schemaVersion(Integer version) { * exists, then it will create a new file store and open; otherwise it will * open the existing file store. *

- * - * - * NOTE: If the database is corrupted somehow then at the time of opening, it will + *

+ * NOTE: If the database is corrupted somehow then at the time of opening, it will * try to repair it using the last known good version. If still it fails to * recover, then it will throw a {@link org.dizitart.no2.exceptions.NitriteIOException}. * @@ -106,15 +120,15 @@ public Nitrite openOrCreate() { * While opening an existing database, it will use the specified credentials * to open it. *

- * - * NOTE: If the database is corrupted somehow then at the time of opening, it will + *

+ * NOTE: If the database is corrupted somehow then at the time of opening, it will * try to repair it using the last known good version. If still it fails to * recover, then it will throw a {@link org.dizitart.no2.exceptions.NitriteIOException}. * * @param username the username * @param password the password * @return the nitrite database instance. - * @throws SecurityException if the user credentials are wrong or one of them is empty string. + * @throws NitriteSecurityException if the user credentials are wrong or one of them is empty string. * @throws org.dizitart.no2.exceptions.NitriteIOException if unable to create a new in-memory database. * @throws org.dizitart.no2.exceptions.NitriteIOException if the database is corrupt and recovery fails. * @throws org.dizitart.no2.exceptions.NitriteIOException if the directory does not exist. diff --git a/nitrite/src/main/java/org/dizitart/no2/NitriteConfig.java b/nitrite/src/main/java/org/dizitart/no2/NitriteConfig.java index 225470598..d97c041bf 100644 --- a/nitrite/src/main/java/org/dizitart/no2/NitriteConfig.java +++ b/nitrite/src/main/java/org/dizitart/no2/NitriteConfig.java @@ -21,13 +21,14 @@ import lombok.ToString; import lombok.extern.slf4j.Slf4j; import org.dizitart.no2.common.Constants; +import org.dizitart.no2.exceptions.IndexingException; import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.index.Indexer; -import org.dizitart.no2.mapper.NitriteMapper; +import org.dizitart.no2.index.NitriteIndexer; +import org.dizitart.no2.common.mapper.NitriteMapper; import org.dizitart.no2.migration.Migration; -import org.dizitart.no2.module.NitriteModule; -import org.dizitart.no2.module.NitritePlugin; -import org.dizitart.no2.module.PluginManager; +import org.dizitart.no2.common.module.NitriteModule; +import org.dizitart.no2.common.module.NitritePlugin; +import org.dizitart.no2.common.module.PluginManager; import org.dizitart.no2.store.NitriteStore; import java.util.HashMap; @@ -44,16 +45,18 @@ @ToString public class NitriteConfig { /** - * Gets the embedded field separator character. Default value - * is `.` unless set explicitly. - * - * @return the embedded field separator character. + * Indicates if this {@link NitriteConfig} is already configured. */ - @Getter - private static String fieldSeparator = "."; + protected boolean configured = false; + /** + * Returns the {@link PluginManager} instance. + */ @Getter(AccessLevel.PACKAGE) - private final PluginManager pluginManager; + protected final PluginManager pluginManager; + + @Getter + private static String fieldSeparator = "."; @Getter private final Map> migrations; @@ -61,8 +64,9 @@ public class NitriteConfig { @Getter private Integer schemaVersion = Constants.INITIAL_SCHEMA_VERSION; - private boolean configured = false; - + /** + * Instantiates a new {@link NitriteConfig}. + */ public NitriteConfig() { this.pluginManager = new PluginManager(this); this.migrations = new HashMap<>(); @@ -83,7 +87,7 @@ public void fieldSeparator(String separator) { } /** - * Loads {@link NitritePlugin} instances. + * Loads {@link NitritePlugin} instances defined in the {@link NitriteModule}. * * @param module the {@link NitriteModule} instances. * @return the {@link NitriteConfig} instance. @@ -97,6 +101,12 @@ public NitriteConfig loadModule(NitriteModule module) { return this; } + /** + * Adds schema migration instructions. + * + * @param migration the migration + * @return the nitrite config + */ @SuppressWarnings("Java8MapApi") public NitriteConfig addMigration(Migration migration) { if (configured) { @@ -121,6 +131,12 @@ public NitriteConfig addMigration(Migration migration) { return this; } + /** + * Sets the current schema version. + * + * @param version the version + * @return the nitrite config + */ public NitriteConfig schemaVersion(Integer version) { if (configured) { throw new InvalidOperationException("cannot add schema version info after database" + @@ -133,7 +149,6 @@ public NitriteConfig schemaVersion(Integer version) { /** * Auto configures nitrite database with default configuration values and * default built-in plugins. - * */ public void autoConfigure() { if (configured) { @@ -144,15 +159,19 @@ public void autoConfigure() { } /** - * Finds an {@link Indexer} by indexType. + * Finds an {@link NitriteIndexer} by indexType. * - * @param indexType the type of {@link Indexer} to find. - * @return the {@link Indexer} + * @param indexType the type of {@link NitriteIndexer} to find. + * @return the {@link NitriteIndexer} */ - public Indexer findIndexer(String indexType) { - Indexer indexer = pluginManager.getIndexerMap().get(indexType); - indexer.initialize(this); - return indexer; + public NitriteIndexer findIndexer(String indexType) { + NitriteIndexer nitriteIndexer = pluginManager.getIndexerMap().get(indexType); + if (nitriteIndexer != null) { + nitriteIndexer.initialize(this); + return nitriteIndexer; + } else { + throw new IndexingException("no indexer found for index type " + indexType); + } } /** @@ -173,7 +192,10 @@ public NitriteStore getNitriteStore() { return pluginManager.getNitriteStore(); } - void initialized() { + /** + * Initializes this {@link NitriteConfig} instance. + */ + protected void initialize() { this.configured = true; this.pluginManager.initializePlugins(); } diff --git a/nitrite/src/main/java/org/dizitart/no2/NitriteDatabase.java b/nitrite/src/main/java/org/dizitart/no2/NitriteDatabase.java index 81e5c2d6a..21a79caf7 100644 --- a/nitrite/src/main/java/org/dizitart/no2/NitriteDatabase.java +++ b/nitrite/src/main/java/org/dizitart/no2/NitriteDatabase.java @@ -23,13 +23,14 @@ import org.dizitart.no2.common.concurrent.LockService; import org.dizitart.no2.exceptions.NitriteException; import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.SecurityException; +import org.dizitart.no2.exceptions.NitriteSecurityException; import org.dizitart.no2.migration.MigrationManager; import org.dizitart.no2.repository.ObjectRepository; import org.dizitart.no2.repository.RepositoryFactory; -import org.dizitart.no2.store.DatabaseMetaData; +import org.dizitart.no2.store.StoreMetaData; import org.dizitart.no2.store.NitriteMap; import org.dizitart.no2.store.NitriteStore; +import org.dizitart.no2.store.UserAuthenticationService; import org.dizitart.no2.transaction.Session; import java.io.File; @@ -38,11 +39,12 @@ import static org.dizitart.no2.common.Constants.NITRITE_VERSION; import static org.dizitart.no2.common.Constants.STORE_INFO; +import static org.dizitart.no2.common.util.ObjectUtils.findRepositoryName; import static org.dizitart.no2.common.util.StringUtils.isNullOrEmpty; -import static org.dizitart.no2.store.StoreSecurity.authenticate; /** * @author Anindya Chatterjee. + * @since 4.0 */ @Slf4j class NitriteDatabase implements Nitrite { @@ -50,6 +52,7 @@ class NitriteDatabase implements Nitrite { private final RepositoryFactory repositoryFactory; private final NitriteConfig nitriteConfig; private final LockService lockService; + private NitriteMap storeInfo; private NitriteStore store; NitriteDatabase(NitriteConfig config) { @@ -88,6 +91,26 @@ public ObjectRepository getRepository(Class type, String key) { return repositoryFactory.getRepository(nitriteConfig, type, key); } + @Override + public void destroyCollection(String name) { + checkOpened(); + store.removeMap(name); + } + + @Override + public void destroyRepository(Class type) { + checkOpened(); + String mapName = findRepositoryName(type, null); + store.removeMap(mapName); + } + + @Override + public void destroyRepository(Class type, String key) { + checkOpened(); + String mapName = findRepositoryName(type, key); + store.removeMap(mapName); + } + @Override public Set listCollectionNames() { checkOpened(); @@ -139,6 +162,7 @@ public synchronized void close() { repositoryFactory.clear(); collectionFactory.clear(); + storeInfo.close(); store.close(); log.info("Nitrite database has been closed successfully."); } catch (NitriteIOException e) { @@ -162,16 +186,13 @@ public void commit() { } @Override - public DatabaseMetaData getDatabaseMetaData() { - NitriteMap storeInfo = this.store.openMap(STORE_INFO, - String.class, Document.class); - + public StoreMetaData getDatabaseMetaData() { Document document = storeInfo.get(STORE_INFO); if (document == null) { prepareDatabaseMetaData(); document = storeInfo.get(STORE_INFO); } - return new DatabaseMetaData(document); + return new StoreMetaData(document); } @Override @@ -181,16 +202,16 @@ public Session createSession() { private void validateUserCredentials(String username, String password) { if (isNullOrEmpty(username)) { - throw new SecurityException("username cannot be empty"); + throw new NitriteSecurityException("username cannot be empty"); } if (isNullOrEmpty(password)) { - throw new SecurityException("password cannot be empty"); + throw new NitriteSecurityException("password cannot be empty"); } } private void initialize(String username, String password) { try { - nitriteConfig.initialized(); + nitriteConfig.initialize(); store = nitriteConfig.getNitriteStore(); boolean isExisting = isExisting(); @@ -200,34 +221,44 @@ private void initialize(String username, String password) { MigrationManager migrationManager = new MigrationManager(this); migrationManager.doMigrate(); - authenticate(store, username, password, isExisting); + UserAuthenticationService userAuthenticationService = new UserAuthenticationService(store); + userAuthenticationService.authenticate(username, password, isExisting); } catch (NitriteException e) { log.error("Error while initializing the database", e); if (store != null && !store.isClosed()) { - store.close(); + try { + store.close(); + } catch (Exception ex) { + log.error("Error while closing the database", ex); + throw new NitriteIOException("failed to close database", ex); + } } throw e; } catch (Exception e) { log.error("Error while initializing the database", e); if (store != null && !store.isClosed()) { - store.close(); + try { + store.close(); + } catch (Exception ex) { + log.error("Error while closing the database"); + throw new NitriteIOException("failed to close database", ex); + } } throw new NitriteIOException("failed to initialize database", e); } } private void prepareDatabaseMetaData() { - NitriteMap storeInfo = this.store.openMap(STORE_INFO, - String.class, Document.class); + storeInfo = this.store.openMap(STORE_INFO, String.class, Document.class); if (storeInfo.isEmpty()) { - DatabaseMetaData databaseMetadata = new DatabaseMetaData(); - databaseMetadata.setCreateTime(System.currentTimeMillis()); - databaseMetadata.setStoreVersion(store.getStoreVersion()); - databaseMetadata.setNitriteVersion(NITRITE_VERSION); - databaseMetadata.setSchemaVersion(nitriteConfig.getSchemaVersion()); + StoreMetaData storeMetadata = new StoreMetaData(); + storeMetadata.setCreateTime(System.currentTimeMillis()); + storeMetadata.setStoreVersion(store.getStoreVersion()); + storeMetadata.setNitriteVersion(NITRITE_VERSION); + storeMetadata.setSchemaVersion(nitriteConfig.getSchemaVersion()); - storeInfo.put(STORE_INFO, databaseMetadata.getInfo()); + storeInfo.put(STORE_INFO, storeMetadata.getInfo()); } } diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/CollectionFactory.java b/nitrite/src/main/java/org/dizitart/no2/collection/CollectionFactory.java index bc2de5860..5a92b43ab 100644 --- a/nitrite/src/main/java/org/dizitart/no2/collection/CollectionFactory.java +++ b/nitrite/src/main/java/org/dizitart/no2/collection/CollectionFactory.java @@ -18,17 +18,17 @@ import org.dizitart.no2.NitriteConfig; import org.dizitart.no2.common.concurrent.LockService; +import org.dizitart.no2.exceptions.NitriteIOException; import org.dizitart.no2.exceptions.ValidationException; import org.dizitart.no2.store.NitriteMap; import org.dizitart.no2.store.NitriteStore; +import org.dizitart.no2.store.StoreCatalog; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.concurrent.locks.Lock; -import static org.dizitart.no2.common.Constants.COLLECTION_CATALOG; -import static org.dizitart.no2.common.Constants.TAG_COLLECTIONS; import static org.dizitart.no2.common.util.ValidationUtils.notEmpty; import static org.dizitart.no2.common.util.ValidationUtils.notNull; @@ -74,21 +74,20 @@ private NitriteCollection createCollection(String name, NitriteConfig nitriteCon if (writeCatalog) { // ignore repository request if (store.getRepositoryRegistry().contains(name)) { + nitriteMap.close(); throw new ValidationException("a repository with same name already exists"); } for (Set set : store.getKeyedRepositoryRegistry().values()) { if (set.contains(name)) { + nitriteMap.close(); throw new ValidationException("a keyed repository with same name already exists"); } } collectionMap.put(name, collection); - NitriteMap catalogMap = store.openMap(COLLECTION_CATALOG, String.class, Document.class); - Document document = catalogMap.get(TAG_COLLECTIONS); - if (document == null) document = Document.createDocument(); - document.put(name, true); - catalogMap.put(TAG_COLLECTIONS, document); + StoreCatalog storeCatalog = store.getCatalog(); + storeCatalog.writeCollectionEntry(name); } return collection; @@ -102,6 +101,8 @@ public void clear() { collection.close(); } collectionMap.clear(); + } catch (Exception e) { + throw new NitriteIOException("failed to close a collection", e); } finally { lock.unlock(); } diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/DefaultNitriteCollection.java b/nitrite/src/main/java/org/dizitart/no2/collection/DefaultNitriteCollection.java index 9ffa2944f..944ba4452 100644 --- a/nitrite/src/main/java/org/dizitart/no2/collection/DefaultNitriteCollection.java +++ b/nitrite/src/main/java/org/dizitart/no2/collection/DefaultNitriteCollection.java @@ -22,6 +22,7 @@ import org.dizitart.no2.collection.events.CollectionEventListener; import org.dizitart.no2.collection.meta.Attributes; import org.dizitart.no2.collection.operation.CollectionOperations; +import org.dizitart.no2.common.Fields; import org.dizitart.no2.common.WriteResult; import org.dizitart.no2.common.concurrent.LockService; import org.dizitart.no2.common.event.EventBus; @@ -31,12 +32,14 @@ import org.dizitart.no2.exceptions.NitriteIOException; import org.dizitart.no2.exceptions.NotIdentifiableException; import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexEntry; +import org.dizitart.no2.index.IndexDescriptor; import org.dizitart.no2.index.IndexOptions; import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.processors.Processor; import org.dizitart.no2.store.NitriteMap; import org.dizitart.no2.store.NitriteStore; +import java.util.Arrays; import java.util.Collection; import java.util.concurrent.locks.Lock; @@ -74,6 +77,20 @@ class DefaultNitriteCollection implements NitriteCollection { initialize(); } + @Override + public void addProcessor(Processor processor) { + checkOpened(); + notNull(processor, "a null processor cannot be added"); + collectionOperations.addProcessor(processor); + } + + @Override + public void removeProcessor(Processor processor) { + checkOpened(); + notNull(processor, "a null processor cannot be removed"); + collectionOperations.removeProcessor(processor); + } + public WriteResult insert(Document[] documents) { checkOpened(); notNull(documents, "a null document cannot be inserted"); @@ -155,72 +172,61 @@ public void clear() { } } - public DocumentCursor find() { + public DocumentCursor find(Filter filter, FindOptions findOptions) { checkOpened(); try { readLock.lock(); - return collectionOperations.find(); + return collectionOperations.find(filter, findOptions); } finally { readLock.unlock(); } } - public DocumentCursor find(Filter filter) { + public void createIndex(IndexOptions indexOptions, String... fields) { checkOpened(); + notNull(fields, "fields cannot be null"); - try { - readLock.lock(); - return collectionOperations.find(filter); - } finally { - readLock.unlock(); - } - } - - public void createIndex(String field, IndexOptions indexOptions) { - checkOpened(); - notNull(field, "field cannot be null"); - - // by default async is false while creating index + Fields indexFields = Fields.withNames(fields); try { writeLock.lock(); if (indexOptions == null) { - collectionOperations.createIndex(field, IndexType.Unique, false); + collectionOperations.createIndex(indexFields, IndexType.UNIQUE); } else { - collectionOperations.createIndex(field, indexOptions.getIndexType(), - indexOptions.isAsync()); + collectionOperations.createIndex(indexFields, indexOptions.getIndexType()); } } finally { writeLock.unlock(); } } - public void rebuildIndex(String field, boolean isAsync) { + public void rebuildIndex(String... fields) { checkOpened(); - notNull(field, "field cannot be null"); + notNull(fields, "fields cannot be null"); - IndexEntry indexEntry; + IndexDescriptor indexDescriptor; + Fields indexFields = Fields.withNames(fields); try { readLock.lock(); - indexEntry = collectionOperations.findIndex(field); + indexDescriptor = collectionOperations.findIndex(indexFields); } finally { readLock.unlock(); } - if (indexEntry != null) { - validateRebuildIndex(indexEntry); + if (indexDescriptor != null) { + validateRebuildIndex(indexDescriptor); try { writeLock.lock(); - collectionOperations.rebuildIndex(indexEntry, isAsync); + collectionOperations.rebuildIndex(indexDescriptor); } finally { writeLock.unlock(); } } else { - throw new IndexingException(field + " is not indexed"); + throw new IndexingException(Arrays.toString(fields) + " is not indexed"); } } - public Collection listIndices() { + public Collection listIndices() { checkOpened(); try { @@ -231,37 +237,40 @@ public Collection listIndices() { } } - public boolean hasIndex(String field) { + public boolean hasIndex(String... fields) { checkOpened(); - notNull(field, "field cannot be null"); + notNull(fields, "fields cannot be null"); + Fields indexFields = Fields.withNames(fields); try { readLock.lock(); - return collectionOperations.hasIndex(field); + return collectionOperations.hasIndex(indexFields); } finally { readLock.unlock(); } } - public boolean isIndexing(String field) { + public boolean isIndexing(String... fields) { checkOpened(); - notNull(field, "field cannot be null"); + notNull(fields, "field cannot be null"); + Fields indexFields = Fields.withNames(fields); try { readLock.lock(); - return collectionOperations.isIndexing(field); + return collectionOperations.isIndexing(indexFields); } finally { readLock.unlock(); } } - public void dropIndex(String field) { + public void dropIndex(String... fields) { checkOpened(); - notNull(field, "field cannot be null"); + notNull(fields, "fields cannot be null"); + Fields indexFields = Fields.withNames(fields); try { writeLock.lock(); - collectionOperations.dropIndex(field); + collectionOperations.dropIndex(indexFields); } finally { writeLock.unlock(); } @@ -295,25 +304,47 @@ public void drop() { try { writeLock.lock(); - collectionOperations.dropCollection(); + + if (collectionOperations != null) { + // close collection and indexes + collectionOperations.close(); + + // drop collection and indexes + collectionOperations.dropCollection(); + } + + // set all reference to null + this.nitriteMap = null; + this.nitriteConfig = null; + this.collectionOperations = null; + this.nitriteStore = null; + + // close event bus + closeEventBus(); } finally { writeLock.unlock(); } isDropped = true; - close(); } public boolean isOpen() { if (nitriteStore == null || nitriteStore.isClosed() || isDropped) { - close(); + try { + close(); + } catch (Exception e) { + throw new NitriteIOException("failed to close the database", e); + } return false; } else return true; } public void close() { if (collectionOperations != null) { + // close collection and indexes collectionOperations.close(); } + + // set all reference to null this.nitriteMap = null; this.nitriteConfig = null; this.collectionOperations = null; @@ -407,11 +438,12 @@ private void checkOpened() { } } - private void validateRebuildIndex(IndexEntry indexEntry) { - notNull(indexEntry, "index cannot be null"); + private void validateRebuildIndex(IndexDescriptor indexDescriptor) { + notNull(indexDescriptor, "index cannot be null"); - if (isIndexing(indexEntry.getField())) { - throw new IndexingException("indexing on value " + indexEntry.getField() + " is currently running"); + String[] indexFields = indexDescriptor.getIndexFields().getFieldNames().toArray(new String[0]); + if (isIndexing(indexFields)) { + throw new IndexingException("indexing on value " + indexDescriptor.getIndexFields() + " is currently running"); } } diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/Document.java b/nitrite/src/main/java/org/dizitart/no2/collection/Document.java index 2e561b9b1..871600e46 100644 --- a/nitrite/src/main/java/org/dizitart/no2/collection/Document.java +++ b/nitrite/src/main/java/org/dizitart/no2/collection/Document.java @@ -26,47 +26,143 @@ import static org.dizitart.no2.common.Constants.*; /** + * A representation of a nitrite document. + * + * @since 1.0 * @author Anindya Chatterjee */ public interface Document extends Iterable>, Cloneable, Serializable { + /** + * Creates a new empty document. + * + * @return the document + */ static Document createDocument() { return new NitriteDocument(); } + /** + * Creates a new document initialized with the given key/value pair. + * + * @param key the key + * @param value the value + * @return the document + */ static Document createDocument(String key, Object value) { LinkedHashMap document = new LinkedHashMap<>(); document.put(key, value); return new NitriteDocument(document); } + /** + * Creates a new document initialized with the given map. + * + * @param documentMap the map + * @return the document + */ static Document createDocument(Map documentMap) { LinkedHashMap document = new LinkedHashMap<>(documentMap); return new NitriteDocument(document); } + /** + * Associates the specified value with the specified key in this document. + *

+ * NOTE: An embedded field is also supported. + *

+ * + * @param key the key + * @param value the value + * @return the document + */ Document put(final String key, final Object value); + /** + * Returns the value to which the specified key is associated with, + * or null if this document contains no mapping for the key. + * + * @param key the key + * @return the object + */ Object get(String key); + /** + * Returns the value of type {@code } to which the specified + * key is associated, or null if this document contains no mapping + * for the key. + * + * @param the type parameter + * @param key the key + * @param type the type + * @return the value + */ T get(String key, Class type); + /** + * Return the nitrite id associated with this document. + * + * @return the nitrite id + */ NitriteId getId(); + /** + * Retrieves all fields (top level and embedded) associated + * with this document. + * + * @return the fields + */ Set getFields(); + /** + * Checks if this document has a nitrite id. + * + * @return the boolean + */ boolean hasId(); + /** + * Removes the key and its value from the document. + * + * @param key the key + */ void remove(String key); + /** + * Creates and returns a copy of this document. + * + * @return document + * */ Document clone(); + /** + * Returns the number of entries in the document. + * + * @return the int + */ int size(); + /** + * Merges a document in this document. + * + * @param update the update + * @return the document + */ Document merge(Document update); + /** + * Checks if a key exists in the document. + * + * @param key the key + * @return the boolean + */ boolean containsKey(String key); + /** + * Gets the document revision number. + * + * @return the revision + */ default Integer getRevision() { if (!containsKey(DOC_REVISION)) { return 0; @@ -74,6 +170,11 @@ default Integer getRevision() { return get(DOC_REVISION, Integer.class); } + /** + * Gets the source of this document. + * + * @return the source + */ default String getSource() { if (!containsKey(DOC_SOURCE)) { return ""; @@ -81,6 +182,11 @@ default String getSource() { return get(DOC_SOURCE, String.class); } + /** + * Gets last modified time of this document since epoch. + * + * @return the last modified since epoch + */ default Long getLastModifiedSinceEpoch() { if (!containsKey(DOC_MODIFIED)) { return 0L; diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/DocumentCursor.java b/nitrite/src/main/java/org/dizitart/no2/collection/DocumentCursor.java index ca4fcbf10..ea0dacca3 100644 --- a/nitrite/src/main/java/org/dizitart/no2/collection/DocumentCursor.java +++ b/nitrite/src/main/java/org/dizitart/no2/collection/DocumentCursor.java @@ -17,44 +17,44 @@ package org.dizitart.no2.collection; import org.dizitart.no2.common.Lookup; -import org.dizitart.no2.common.NullOrder; import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.common.SortOrder; - -import java.text.Collator; /** * An interface to iterate over database {@code find()} results. It provides a * mechanism to iterate over all {@link NitriteId}s of the result. - *

- * [[app-listing]] - * [source,java] - * .Example of {@link DocumentCursor} - * -- + *

+ * {@code
  * // create/open a database
  * Nitrite db = Nitrite.builder()
- * .openOrCreate("user", "password");
- * 

+ * .openOrCreate("user", "password"); + * + * // create/open a database + * Nitrite db = Nitrite.builder() + * .openOrCreate("user", "password"); + * * // create a collection named - test * NitriteCollection collection = db.getCollection("test"); - *

+ * * // returns all ids un-filtered * DocumentCursor result = collection.find(); - *

+ * * for (Document doc : result) { - * // use your logic with the retrieved doc here + * // use your logic with the retrieved doc here * } - *

- * -- + * + * }* + *
* * @author Anindya Chatterjee * @since 4.0 */ public interface DocumentCursor extends RecordStream { - - DocumentCursor sort(String field, SortOrder sortOrder, Collator collator, NullOrder nullOrder); - - DocumentCursor skipLimit(long skip, long size); + /** + * Gets a filter plan for the query. + * + * @return the filter plan + */ + FindPlan getFindPlan(); /** * Gets a lazy iterable containing all the selected keys of the result documents. @@ -77,28 +77,4 @@ public interface DocumentCursor extends RecordStream { * @since 2.1.0 */ RecordStream join(DocumentCursor foreignCursor, Lookup lookup); - - default DocumentCursor skip(long skip) { - return skipLimit(skip, size()); - } - - default DocumentCursor limit(long limit) { - return skipLimit(0, limit); - } - - default DocumentCursor sort(String field) { - return sort(field, SortOrder.Ascending); - } - - default DocumentCursor sort(String field, SortOrder sortOrder) { - return sort(field, sortOrder, NullOrder.Default); - } - - default DocumentCursor sort(String field, SortOrder sortOrder, Collator collator) { - return sort(field, sortOrder, collator, NullOrder.Default); - } - - default DocumentCursor sort(String field, SortOrder sortOrder, NullOrder nullOrder) { - return sort(field, sortOrder, null, nullOrder); - } } diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/FindOptions.java b/nitrite/src/main/java/org/dizitart/no2/collection/FindOptions.java new file mode 100644 index 000000000..ae8518902 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/collection/FindOptions.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.collection; + +import lombok.AccessLevel; +import lombok.Data; +import lombok.Setter; +import lombok.experimental.Accessors; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.common.SortableFields; + +import java.text.Collator; + +/** + * The options for find operation. + * + * @since 1.0 + * @author Anindya Chatterjee + */ +@Data +@Accessors(fluent = true, chain = true) +@Setter(AccessLevel.PACKAGE) +public class FindOptions { + private SortableFields orderBy; + private Long skip; + private Long limit; + + @Setter(AccessLevel.PUBLIC) + private Collator collator; + + public FindOptions() { + this.collator = Collator.getInstance(); + } + + public static FindOptions orderBy(String fieldName, SortOrder sortOrder) { + SortableFields fields = new SortableFields(); + fields.addField(fieldName, sortOrder); + + FindOptions findOptions = new FindOptions(); + findOptions.orderBy(fields); + return findOptions; + } + + public static FindOptions skipBy(long skip) { + FindOptions findOptions = new FindOptions(); + findOptions.skip(skip); + return findOptions; + } + + public static FindOptions limitBy(long limit) { + FindOptions findOptions = new FindOptions(); + findOptions.limit(limit); + return findOptions; + } + + public FindOptions skip(Long skip) { + this.skip = skip; + return this; + } + + public FindOptions skip(Integer skip) { + this.skip = skip == null ? null : (long) skip; + return this; + } + + public FindOptions limit(Long limit) { + this.limit = limit; + return this; + } + + public FindOptions limit(Integer limit) { + this.limit = limit == null ? null : (long) limit; + return this; + } + + public FindOptions thenOrderBy(String fieldName, SortOrder sortOrder) { + if (orderBy != null) { + orderBy.addField(fieldName, sortOrder); + } else { + SortableFields fields = new SortableFields(); + fields.addField(fieldName, sortOrder); + orderBy = fields; + } + return this; + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/FindPlan.java b/nitrite/src/main/java/org/dizitart/no2/collection/FindPlan.java new file mode 100644 index 000000000..225d5aa47 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/collection/FindPlan.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.collection; + +import lombok.Data; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.filters.EqualsFilter; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.filters.IndexScanFilter; +import org.dizitart.no2.index.IndexDescriptor; + +import java.text.Collator; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Represents an execution plan of a find operation after optimization. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +@Data +public class FindPlan { + private EqualsFilter byIdFilter; + private IndexScanFilter indexScanFilter; + private Filter collectionScanFilter; + + private IndexDescriptor indexDescriptor; + private Map indexScanOrder; + private List> blockingSortOrder; + + private Long skip; + private Long limit; + + private Collator collator; + + private List subPlans; + + public FindPlan() { + this.subPlans = new ArrayList<>(); + this.blockingSortOrder = new ArrayList<>(); + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/NitriteCollection.java b/nitrite/src/main/java/org/dizitart/no2/collection/NitriteCollection.java index 57da139de..dbe8ff951 100644 --- a/nitrite/src/main/java/org/dizitart/no2/collection/NitriteCollection.java +++ b/nitrite/src/main/java/org/dizitart/no2/collection/NitriteCollection.java @@ -42,17 +42,18 @@ * A nitrite collection supports indexing. Every nitrite collection is also * observable. *

- * [[app-listing]] - * [source,java] - * .Create a collection - * -- - * // create/open a database + *

Create a collection

+ *
+ * {@code
  * Nitrite db = Nitrite.builder()
- * .openOrCreate("user", "password");
- * 

- * include::/src/docs/asciidoc/examples/collection.adoc[] - *

- * -- + * .loadModule(MVStoreModule("/tmp/tmp.db")) + * .openOrCreate("user", "password"); + * + * NitriteCollection collection = db.getCollection("products"); + * } + *

+ * + *

* * @author Anindya Chatterjee * @see EventAware @@ -64,29 +65,29 @@ */ public interface NitriteCollection extends PersistentCollection { /** - * Insert documents into a collection. If the document contains a '_id' value, then + * Insert documents into a collection. If the document contains a {@code _id} value, then * the value will be used as a unique key to identify the document in the collection. - * If the document does not contain any '_id' value, then nitrite will generate a new + * If the document does not contain any {@code _id} value, then nitrite will generate a new * {@link NitriteId} and will add it to the document. *

* If any of the value is already indexed in the collection, then after insertion the * index will also be updated. *

- * [icon="{@docRoot}/note.png"] * NOTE: These operations will notify all {@link CollectionEventListener} * instances registered to this collection with change type * {@link EventType#Insert}. - * + *

+ * * @param document the document to insert * @param documents other documents to insert in a batch. * @return the result of write operation. - * @throws ValidationException if `document` is `null`. - * @throws InvalidIdException if the '_id' value contains `null` value. - * @throws InvalidIdException if the '_id' value contains non comparable type, i.e. + * @throws ValidationException if {@code document} is {@code null}. + * @throws InvalidIdException if the {@code _id} value contains {@code null} value. + * @throws InvalidIdException if the {@code _id} value contains non comparable type, i.e. * type that does not implement {@link Comparable}. - * @throws InvalidIdException if the '_id' contains value, which is not of the same java - * type as of other documents' '_id' in the collection. - * @throws UniqueConstraintException if the value of '_id' value clashes with the id + * @throws InvalidIdException if the {@code _id} contains value, which is not of the same java + * type as of other documents' {@code _id} in the collection. + * @throws UniqueConstraintException if the value of {@code _id} value clashes with the id * of another document in the collection. * @throws UniqueConstraintException if a value of the document is indexed and it * violates the unique constraint in the collection(if any). @@ -112,17 +113,17 @@ default WriteResult insert(Document document, Document... documents) { /** * Update documents in the collection. *

- * If the `filter` is `null`, it will update all documents in the collection. + * If the {@code filter} is {@code null}, it will update all documents in the collection. *

- * [icon="{@docRoot}/note.png"] * NOTE: This operations will notify all {@link CollectionEventListener} * instances registered to this collection with change type * {@link EventType#Update}. + *

* * @param filter the filter to apply to select documents from the collection. * @param update the modifications to apply. * @return the result of the update operation. - * @throws ValidationException if the `update` document is `null`. + * @throws ValidationException if the {@code update} document is {@code null}. */ default WriteResult update(Filter filter, Document update) { return update(filter, update, new UpdateOptions()); @@ -130,22 +131,22 @@ default WriteResult update(Filter filter, Document update) { /** * Updates document in the collection. Update operation can be customized - * with the help of `updateOptions`. + * with the help of {@code updateOptions}. *

- * If the `filter` is `null`, it will update all documents in the collection unless - * `justOnce` is set to `true` in `updateOptions`. + * If the {@code filter} is {@code null}, it will update all documents in the collection unless + * {@code justOnce} is set to {@code true} in {@code updateOptions}. *

- * [icon="{@docRoot}/note.png"] * NOTE: This operations will notify all {@link CollectionEventListener} * instances registered to this collection with change type * {@link EventType#Update} or {@link EventType#Insert}. + *

* * @param filter the filter to apply to select documents from the collection. * @param update the modifications to apply. * @param updateOptions the update options to customize the operation. * @return the result of the update operation. - * @throws ValidationException if the `update` document is `null`. - * @throws ValidationException if `updateOptions` is `null`. + * @throws ValidationException if the {@code update} document is {@code null}. + * @throws ValidationException if {@code updateOptions} is {@code null}. * @see UpdateOptions */ WriteResult update(Filter filter, Document update, UpdateOptions updateOptions); @@ -153,12 +154,12 @@ default WriteResult update(Filter filter, Document update) { /** * Removes matching elements from the collection. *

- * If the `filter` is `null`, it will remove all objects from the collection. + * If the {@code filter} is {@code null}, it will remove all objects from the collection. *

- * [icon="{@docRoot}/note.png"] * NOTE: This operations will notify all {@link CollectionEventListener} * instances registered to this collection with change type * {@link EventType#Remove}. + *

* * @param filter the filter to apply to select elements from collection. * @return the result of the remove operation. @@ -169,15 +170,15 @@ default WriteResult remove(Filter filter) { /** * Removes document from a collection. Remove operation can be customized by - * `removeOptions`. + * {@code removeOptions}. *

- * If the `filter` is `null`, it will remove all documents in the collection unless - * `justOnce` is set to `true` in `removeOptions`. + * If the {@code filter} is {@code null}, it will remove all documents in the collection unless + * {@code justOnce} is set to {@code true} in {@code removeOptions}. *

- * [icon="{@docRoot}/note.png"] * NOTE: This operations will notify all {@link CollectionEventListener} * instances registered to this collection with change type * {@link EventType#Remove}. + *

* * @param filter the filter to apply to select documents from collection. * @param justOne indicates if only one element will be removed or all of them. @@ -190,7 +191,9 @@ default WriteResult remove(Filter filter) { * * @return a cursor to all documents in the collection. */ - DocumentCursor find(); + default DocumentCursor find() { + return find(Filter.ALL, null); + } /** * Applies a filter on the collection and returns a cursor to the @@ -198,25 +201,53 @@ default WriteResult remove(Filter filter) { *

* See {@link Filter} for all available filters. *

- * [icon="{@docRoot}/note.png"] * NOTE: If there is an index on the value specified in the filter, this operation * will take advantage of the index. + *

* * @param filter the filter to apply to select documents from collection. * @return a cursor to all selected documents. - * @throws ValidationException if `filter` is null. + * @throws ValidationException if {@code filter} is null. * @see Filter * @see DocumentCursor#project(Document) */ - DocumentCursor find(Filter filter); + default DocumentCursor find(Filter filter) { + return find(filter, null); + } + + /** + * Returns a customized cursor to all documents in the collection. + * + * @param findOptions specifies pagination, sort options for the cursor. + * @return a cursor to all selected documents. + * @see org.dizitart.no2.common.SortOrder + */ + default DocumentCursor find(FindOptions findOptions) { + return find(Filter.ALL, findOptions); + } + + /** + * Applies a filter on the collection and returns a customized cursor to the + * selected documents. + * + *

+ * NOTE: If there is an index on the value specified in the filter, this operation + * will take advantage of the index. + *

+ * + * @param filter the filter to apply to select documents from collection. + * @param findOptions specifies pagination, sort options for the cursor. + * @return a cursor to all selected documents. + */ + DocumentCursor find(Filter filter, FindOptions findOptions); /** * Gets a single element from the collection by its id. If no element - * is found, it will return `null`. + * is found, it will return {@code null}. * * @param nitriteId the nitrite id * @return the unique document associated with the nitrite id. - * @throws ValidationException if `nitriteId` is `null`. + * @throws ValidationException if `nitriteId` is {@code null}. */ Document getById(NitriteId nitriteId); diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/NitriteDocument.java b/nitrite/src/main/java/org/dizitart/no2/collection/NitriteDocument.java index c8ab8c944..95e418649 100644 --- a/nitrite/src/main/java/org/dizitart/no2/collection/NitriteDocument.java +++ b/nitrite/src/main/java/org/dizitart/no2/collection/NitriteDocument.java @@ -38,12 +38,14 @@ import static org.dizitart.no2.common.util.ValidationUtils.notNull; /** + * A default implementation of nitrite document. + * + * @since 4.0 * @author Anindya Chatterjee */ class NitriteDocument extends LinkedHashMap implements Document { private static final long serialVersionUID = 1477462374L; private static final List reservedFields = listOf(DOC_ID, DOC_REVISION, DOC_SOURCE, DOC_MODIFIED); -// private final String regex = MessageFormat.format("\\{0}", NitriteConfig.getFieldSeparator()); NitriteDocument() { super(); @@ -54,56 +56,66 @@ class NitriteDocument extends LinkedHashMap implements Document } @Override - public Document put(String key, Object value) { - if (isNullOrEmpty(key)) { + public Document put(String field, Object value) { + // field name cannot be empty or null + if (isNullOrEmpty(field)) { throw new InvalidOperationException("document does not support empty or null key"); } - if (DOC_ID.contentEquals(key) && !validId(value)) { + // _id field can not be set manually + if (DOC_ID.contentEquals(field) && !validId(value)) { throw new InvalidOperationException("_id is an auto generated value and cannot be set"); } + // value must be serializable if (value != null && !Serializable.class.isAssignableFrom(value.getClass())) { throw new ValidationException("type " + value.getClass().getName() + " does not implement java.io.Serializable"); } - String regex = MessageFormat.format("\\{0}", NitriteConfig.getFieldSeparator()); - if (key.contains(NitriteConfig.getFieldSeparator())) { - String[] splits = key.split(regex); + // if field name contains field separator, split the fields, and put the value + // accordingly associated with th embedded field. + if (isEmbedded(field)) { + String regex = MessageFormat.format("\\{0}", NitriteConfig.getFieldSeparator()); + String[] splits = field.split(regex); deepPut(splits, value); } else { - super.put(key, value); + super.put(field, value); } return this; } @Override - public Object get(String key) { - if (key != null - && key.contains(NitriteConfig.getFieldSeparator()) - && !containsKey(key)) { - return deepGet(key); + public Object get(String field) { + if (field != null + && isEmbedded(field) + && !containsKey(field)) { + // if field is an embedded field, get it by deep scan + return deepGet(field); } - return super.get(key); + return super.get(field); } @Override - public T get(String key, Class type) { + public T get(String field, Class type) { notNull(type, "type cannot be null"); - return type.cast(get(key)); + return type.cast(get(field)); } @Override public NitriteId getId() { String id; try { + // if _id field is not populated already, create a new id + // and set, otherwise return the existing id if (!containsKey(DOC_ID)) { id = newId().getIdValue(); super.put(DOC_ID, id); } else { id = (String) get(DOC_ID); } + + // create a nitrite id instance from the string value return createId(id); } catch (ClassCastException cce) { throw new InvalidIdException("invalid _id found " + get(DOC_ID)); @@ -112,6 +124,7 @@ public NitriteId getId() { @Override public Set getFields() { + // get all fields except from the reserved ones return getFieldsInternal(""); } @@ -121,21 +134,36 @@ public boolean hasId() { } @Override - public void remove(String key) { - if (key.contains(NitriteConfig.getFieldSeparator())) { + public void remove(String field) { + if (isEmbedded(field)) { + // if the field is an embedded field, + // run a deep scan and remove the last field String regex = MessageFormat.format("\\{0}", NitriteConfig.getFieldSeparator()); - String[] splits = key.split(regex); + String[] splits = field.split(regex); deepRemove(splits); } else { - super.remove(key); + // remove the field from this document + super.remove(field); } } @Override @SuppressWarnings("unchecked") public Document clone() { - Map clone = (Map) super.clone(); - return new NitriteDocument(clone); + Map cloned = (Map) super.clone(); + + // create the clone of any embedded documents as well + for (Map.Entry entry : cloned.entrySet()) { + if (entry.getValue() instanceof Document) { + Document value = (Document) entry.getValue(); + + // this will recursively take care any embedded document + // of the clone as well + Document clonedValue = value.clone(); + cloned.put(entry.getKey(), clonedValue); + } + } + return new NitriteDocument(cloned); } @Override @@ -148,6 +176,7 @@ public Document merge(Document document) { @Override public boolean containsKey(String key) { +// return getFields().contains(key); return super.containsKey(key); } @@ -191,18 +220,27 @@ public Iterator> iterator() { private Set getFieldsInternal(String prefix) { Set fields = new HashSet<>(); + // iterate top level keys for (Pair entry : this) { + // ignore the reserved fields if (reservedFields.contains(entry.getFirst())) continue; Object value = entry.getSecond(); if (value instanceof NitriteDocument) { + // if the value is a document, traverse its fields recursively, + // prefix would be the field name of the document if (isNullOrEmpty(prefix)) { + // level-1 fields fields.addAll(((NitriteDocument) value).getFieldsInternal(entry.getFirst())); } else { + // level-n fields, separated by field separator fields.addAll(((NitriteDocument) value).getFieldsInternal(prefix + NitriteConfig.getFieldSeparator() + entry.getFirst())); } } else if (!(value instanceof Iterable)) { + // if there is no more embedded document, add the field to the list + // and if this is an embedded document then prefix its name by parent fields, + // separated by field separator if (isNullOrEmpty(prefix)) { fields.add(entry.getFirst()); } else { @@ -214,7 +252,8 @@ private Set getFieldsInternal(String prefix) { } private Object deepGet(String field) { - if (field.contains(NitriteConfig.getFieldSeparator())) { + if (isEmbedded(field)) { + // for embedded field, run a deep scan return getByEmbeddedKey(field); } else { return null; @@ -227,15 +266,25 @@ private void deepPut(String[] splits, Object value) { } String key = splits[0]; if (splits.length == 1) { + // if last key, simply put in the current document put(key, value); } else { + // get the object for the current level Object val = get(key); + + // get the remaining embedded fields for next level scan String[] remaining = Arrays.copyOfRange(splits, 1, splits.length); + if (val instanceof NitriteDocument) { + // if the current level value is embedded doc, scan to the next level ((NitriteDocument) val).deepPut(remaining, value); } else if (val == null) { + // if current level value is null, create a new document + // and try to create next level embedded doc by next level scan NitriteDocument subDoc = new NitriteDocument(); subDoc.deepPut(remaining, value); + + // put the newly created document in current level put(key, subDoc); } } @@ -247,17 +296,26 @@ private void deepRemove(String[] splits) { } String key = splits[0]; if (splits.length == 1) { + // if last key, simply remove the current document remove(key); } else { + // get the object for the current level Object val = get(key); + + // get the remaining embedded fields for next level scan String[] remaining = Arrays.copyOfRange(splits, 1, splits.length); + if (val instanceof NitriteDocument) { + // if the current level value is embedded doc, scan to the next level NitriteDocument subDoc = (NitriteDocument) val; - ((NitriteDocument) val).deepRemove(remaining); + subDoc.deepRemove(remaining); if (subDoc.size() == 0) { + // if the next level document is an empty one + // remove the current level document also super.remove(key); } } else if (val == null) { + // if current level value is null, remove the key super.remove(key); } } @@ -265,11 +323,14 @@ private void deepRemove(String[] splits) { private Object getByEmbeddedKey(String embeddedKey) { String regex = MessageFormat.format("\\{0}", NitriteConfig.getFieldSeparator()); + + // split the key String[] path = embeddedKey.split(regex); if (path.length < 1) { return null; } + // get current level value and scan to next level using remaining keys return recursiveGet(get(path[0]), Arrays.copyOfRange(path, 1, path.length)); } @@ -284,68 +345,116 @@ private Object recursiveGet(Object object, String[] remainingPath) { } if (object instanceof Document) { + // if the current level value is document, scan to the next level with remaining keys return recursiveGet(((Document) object).get(remainingPath[0]), Arrays.copyOfRange(remainingPath, 1, remainingPath.length)); } if (object.getClass().isArray()) { + // if the current level value is an array + + // get the first key String accessor = remainingPath[0]; + + // convert current value to object array Object[] array = convertToObjectArray(object); + if (isInteger(accessor)) { + // if the current key is an integer + + // convert the key as an integer index int index = asInteger(accessor); + + // check index lower bound if (index < 0) { throw new ValidationException("invalid array index " + index + " to access item inside a document"); } + // check index upper bound if (index >= array.length) { throw new ValidationException("index " + index + " is not less than the size of the array " + array.length); } + // get the value at the index from the array + // if there are remaining keys, scan to the next level return recursiveGet(array[index], Arrays.copyOfRange(remainingPath, 1, remainingPath.length)); } else { + // if the current key is not an integer, then decompose the + // object array into a list and scan each of the element of the + // list using remaining keys and return a list of all returned + // elements from each of the list items. return decompose(listOf(array), remainingPath); } } if (object instanceof Iterable) { + // if the current level value is an iterable + + // get the first key String accessor = remainingPath[0]; + + // convert current value to object iterable Iterable iterable = (Iterable) object; + + // create a list from the iterable List collection = Iterables.toList(iterable); + if (isInteger(accessor)) { + // if the current key is an integer + + // convert the key as an integer index int index = asInteger(accessor); + + // check index lower bound if (index < 0) { throw new ValidationException("invalid collection index " + index + " to access item inside a document"); } + // check index upper bound if (index >= collection.size()) { throw new ValidationException("index " + accessor + " is not less than the size of the list " + collection.size()); } + // get the value at the index from the list + // if there are remaining keys, scan to the next level return recursiveGet(collection.get(index), Arrays.copyOfRange(remainingPath, 1, remainingPath.length)); } else { + // if the current key is not an integer, then decompose the + // list and scan each of the element of the + // list using remaining keys and return a list of all returned + // elements from each of the list items. return decompose(collection, remainingPath); } } + // if no match found return null return null; } @SuppressWarnings("unchecked") private List decompose(List collection, String[] remainingPath) { Set items = new HashSet<>(); + + // iterate each item for (Object item : collection) { - Object value = recursiveGet(item, remainingPath); - if (value != null) { - if (value instanceof Iterable) { - List list = Iterables.toList((Iterable) value); + + // scan the item using remaining keys + Object result = recursiveGet(item, remainingPath); + + if (result != null) { + if (result instanceof Iterable) { + // if the result is iterable, return everything as a list + List list = Iterables.toList((Iterable) result); items.addAll(list); - } else if (value.getClass().isArray()) { - List list = Arrays.asList(convertToObjectArray(value)); + } else if (result.getClass().isArray()) { + // if the result is an array, return everything as list + List list = Arrays.asList(convertToObjectArray(result)); items.addAll(list); } else { - items.add(value); + // if its neither a iterable not an array, return the item + items.add(result); } } } @@ -354,21 +463,30 @@ private List decompose(List collection, String[] remainingPath) private int asInteger(String number) { try { + // parse the string as an integer return Integer.parseInt(number); } catch (NumberFormatException e) { + // if parsing fails, return invalid integer for document access return -1; } } private boolean isInteger(String value) { try { + // try parse the string as an integer Integer.parseInt(value); return true; } catch (NumberFormatException e) { + // if parsing fails, then value is not an integer return false; } } + private boolean isEmbedded(String field) { + // if the field contains separator character, then it is an embedded field + return field.contains(NitriteConfig.getFieldSeparator()); + } + private void writeObject(ObjectOutputStream stream) throws IOException { stream.writeInt(size()); for (Pair pair : this) { diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/SnowflakeIdGenerator.java b/nitrite/src/main/java/org/dizitart/no2/collection/SnowflakeIdGenerator.java index 9e6ad19fa..097629475 100644 --- a/nitrite/src/main/java/org/dizitart/no2/collection/SnowflakeIdGenerator.java +++ b/nitrite/src/main/java/org/dizitart/no2/collection/SnowflakeIdGenerator.java @@ -36,7 +36,7 @@ *
  • 1 unused sign bit, always set to 0
  • * *

    - * Original code can be found here - https://github.com/apache/marmotta/blob/master/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/generator/SnowflakeIDGenerator.java + * This is a derivative work of - https://github.com/apache/marmotta/blob/master/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/generator/SnowflakeIDGenerator.java *

    * * @author Sebastian Schaffert (sschaffert@apache.org) diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/events/CollectionEventListener.java b/nitrite/src/main/java/org/dizitart/no2/collection/events/CollectionEventListener.java index f14beaea1..290f1493f 100644 --- a/nitrite/src/main/java/org/dizitart/no2/collection/events/CollectionEventListener.java +++ b/nitrite/src/main/java/org/dizitart/no2/collection/events/CollectionEventListener.java @@ -23,14 +23,6 @@ * An interface when implemented makes an object be * able to listen to any changes in a {@link NitriteCollection} * or {@link ObjectRepository}. - *

    - * [[app-listing]] - * [source,java] - * .Example - * -- - *

    - * // observe any change to the collection - * collection.subscribe(new EventListener() { * * @author Anindya Chatterjee. * @since 4.0 diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/meta/Attributes.java b/nitrite/src/main/java/org/dizitart/no2/collection/meta/Attributes.java index 8fd129818..07562d701 100644 --- a/nitrite/src/main/java/org/dizitart/no2/collection/meta/Attributes.java +++ b/nitrite/src/main/java/org/dizitart/no2/collection/meta/Attributes.java @@ -35,26 +35,61 @@ */ @EqualsAndHashCode public class Attributes implements Serializable { + /** + * The constant CREATED_TIME. + */ public static final String CREATED_TIME = "createdTime"; + /** + * The constant LAST_MODIFIED_TIME. + */ public static final String LAST_MODIFIED_TIME = "lastModifiedTime"; + /** + * The constant OWNER. + */ public static final String OWNER = "owner"; + /** + * The constant UNIQUE_ID. + */ public static final String UNIQUE_ID = "uuid"; + /** + * The constant LAST_SYNCED. + */ public static final String LAST_SYNCED = "lastSynced"; + /** + * The constant SYNC_LOCK. + */ public static final String SYNC_LOCK = "syncLock"; + /** + * The constant EXPIRY_WAIT. + */ public static final String EXPIRY_WAIT = "expiryWait"; + /** + * The constant TOMBSTONE. + */ public static final String TOMBSTONE = "tombstone"; + /** + * The constant REPLICA. + */ public static final String REPLICA = "replica"; private static final long serialVersionUID = 1481284930L; @Getter @Setter private Map attributes; + /** + * Instantiates a new Attributes. + */ public Attributes() { attributes = new ConcurrentHashMap<>(); set(CREATED_TIME, Long.toString(System.currentTimeMillis())); set(UNIQUE_ID, java.util.UUID.randomUUID().toString()); } + /** + * Instantiates a new Attributes. + * + * @param collection the collection + */ public Attributes(String collection) { attributes = new ConcurrentHashMap<>(); set(OWNER, collection); @@ -62,16 +97,35 @@ public Attributes(String collection) { set(UNIQUE_ID, java.util.UUID.randomUUID().toString()); } + /** + * Set attributes. + * + * @param key the key + * @param value the value + * @return the attributes + */ public Attributes set(String key, String value) { attributes.put(LAST_MODIFIED_TIME, Long.toString(System.currentTimeMillis())); attributes.put(key, value); return this; } + /** + * Get string value of an attribute. + * + * @param key the key + * @return the string + */ public String get(String key) { return attributes.get(key); } + /** + * Check whether a key exists in the attributes. + * + * @param key the key + * @return the boolean + */ public boolean hasKey(String key) { return attributes.containsKey(key); } diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/operation/BoundedDocumentStream.java b/nitrite/src/main/java/org/dizitart/no2/collection/operation/BoundedDocumentStream.java deleted file mode 100644 index d7091542c..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/collection/operation/BoundedDocumentStream.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection.operation; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.ValidationException; - -import java.util.Collections; -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * @author Anindya Chatterjee. - */ -class BoundedDocumentStream implements RecordStream> { - private final RecordStream> recordStream; - private final long offset; - private final long limit; - - BoundedDocumentStream(RecordStream> recordStream, final long offset, final long limit) { - if (offset < 0) { - throw new ValidationException("offset parameter must not be negative"); - } - if (limit < 0) { - throw new ValidationException("limit parameter must not be negative"); - } - - this.recordStream = recordStream; - this.offset = offset; - this.limit = limit; - } - - @Override - public Iterator> iterator() { - Iterator> iterator = recordStream == null ? Collections.emptyIterator() - : recordStream.iterator(); - return new BoundedIterator<>(iterator, offset, limit); - } - - public static class BoundedIterator implements Iterator { - private final Iterator iterator; - private final long offset; - private final long size; - private long pos; - - public BoundedIterator(final Iterator iterator, final long offset, final long size) { - if (iterator == null) { - throw new ValidationException("iterator must not be null"); - } - if (offset < 0) { - throw new ValidationException("offset parameter must not be negative."); - } - if (size < 0) { - throw new ValidationException("size parameter must not be negative."); - } - - this.iterator = iterator; - this.offset = offset; - this.size = size; - pos = 0; - init(); - } - - private void init() { - while (pos < offset && iterator.hasNext()) { - iterator.next(); - pos++; - } - } - - @Override - public boolean hasNext() { - if (checkBounds()) { - return false; - } - return iterator.hasNext(); - } - - private boolean checkBounds() { - return pos - offset + 1 > size; - } - - @Override - public T next() { - if (checkBounds()) { - throw new NoSuchElementException(); - } - final T next = iterator.next(); - pos++; - return next; - } - - @Override - public void remove() { - if (pos <= offset) { - throw new IllegalStateException("remove() cannot be called before calling next()"); - } - iterator.remove(); - } - } - -} diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/operation/CollectionOperations.java b/nitrite/src/main/java/org/dizitart/no2/collection/operation/CollectionOperations.java index a083c318f..e2513f907 100644 --- a/nitrite/src/main/java/org/dizitart/no2/collection/operation/CollectionOperations.java +++ b/nitrite/src/main/java/org/dizitart/no2/collection/operation/CollectionOperations.java @@ -17,38 +17,49 @@ package org.dizitart.no2.collection.operation; import org.dizitart.no2.NitriteConfig; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.collection.UpdateOptions; +import org.dizitart.no2.collection.*; import org.dizitart.no2.collection.events.CollectionEventInfo; import org.dizitart.no2.collection.events.CollectionEventListener; import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.common.Fields; import org.dizitart.no2.common.WriteResult; import org.dizitart.no2.common.event.EventBus; import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexEntry; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.common.processors.Processor; +import org.dizitart.no2.common.processors.ProcessorChain; import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.store.StoreCatalog; import java.util.Collection; -import java.util.HashSet; -import java.util.Set; -import static org.dizitart.no2.common.Constants.COLLECTION_CATALOG; +import static org.dizitart.no2.collection.UpdateOptions.updateOptions; +import static org.dizitart.no2.common.util.DocumentUtils.createUniqueFilter; /** + * The collection operations. + * * @author Anindya Chatterjee + * @since 1.0 */ -public class CollectionOperations { +public class CollectionOperations implements AutoCloseable { private final String collectionName; private final NitriteConfig nitriteConfig; private final NitriteMap nitriteMap; private final EventBus, CollectionEventListener> eventBus; + private ProcessorChain processorChain; private IndexOperations indexOperations; private WriteOperations writeOperations; private ReadOperations readOperations; + /** + * Instantiates a new Collection operations. + * + * @param collectionName the collection name + * @param nitriteMap the nitrite map + * @param nitriteConfig the nitrite config + * @param eventBus the event bus + */ public CollectionOperations(String collectionName, NitriteMap nitriteMap, NitriteConfig nitriteConfig, @@ -57,82 +68,197 @@ public CollectionOperations(String collectionName, this.nitriteMap = nitriteMap; this.nitriteConfig = nitriteConfig; this.eventBus = eventBus; - init(); + initialize(); + } + + /** + * Adds a document processor. + * + * @param processor the processor + */ + public void addProcessor(Processor processor) { + doProcess(processor); + processorChain.add(processor); + } + + /** + * Removes a document processor. + * + * @param processor the processor + */ + public void removeProcessor(Processor processor) { + processorChain.remove(processor); + undoProcess(processor); } - public void createIndex(String field, String indexType, boolean async) { - indexOperations.ensureIndex(field, indexType, async); + /** + * Creates index. + * + * @param fields the fields + * @param indexType the index type + */ + public void createIndex(Fields fields, String indexType) { + indexOperations.createIndex(fields, indexType); } - public IndexEntry findIndex(String field) { - return indexOperations.findIndexEntry(field); + /** + * Finds index descriptor. + * + * @param fields the fields + * @return the index descriptor + */ + public IndexDescriptor findIndex(Fields fields) { + return indexOperations.findIndexDescriptor(fields); } - public void rebuildIndex(IndexEntry indexEntry, boolean async) { - indexOperations.rebuildIndex(indexEntry, async); + /** + * Rebuilds index. + * + * @param indexDescriptor the index descriptor + */ + public void rebuildIndex(IndexDescriptor indexDescriptor) { + indexOperations.buildIndex(indexDescriptor, true); } - public Collection listIndexes() { + /** + * Lists all indexes. + * + * @return the collection + */ + public Collection listIndexes() { return indexOperations.listIndexes(); } - public boolean hasIndex(String field) { - return indexOperations.hasIndexEntry(field); + /** + * Checks if an index exists on the fields. + * + * @param fields the fields + * @return the boolean + */ + public boolean hasIndex(Fields fields) { + return indexOperations.hasIndexEntry(fields); } - public boolean isIndexing(String field) { - return indexOperations.isIndexing(field); + /** + * Checks if indexing is going on the fields. + * + * @param fields the fields + * @return the boolean + */ + public boolean isIndexing(Fields fields) { + return indexOperations.isIndexing(fields); } - public void dropIndex(String field) { - indexOperations.dropIndex(field); + /** + * Drops index. + * + * @param fields the fields + */ + public void dropIndex(Fields fields) { + indexOperations.dropIndex(fields); } + /** + * Drops all indices. + */ public void dropAllIndices() { indexOperations.dropAllIndices(); } + /** + * Inserts documents to the collection. + * + * @param documents the documents + * @return the write result + */ public WriteResult insert(Document[] documents) { return writeOperations.insert(documents); } + /** + * Updates documents in the collection. + * + * @param filter the filter + * @param update the update + * @param updateOptions the update options + * @return the write result + */ public WriteResult update(Filter filter, Document update, UpdateOptions updateOptions) { return writeOperations.update(filter, update, updateOptions); } + /** + * Removes document from the collection. + * + * @param document the document + * @return the write result + */ public WriteResult remove(Document document) { return writeOperations.remove(document); } + /** + * Removes document from collection. + * + * @param filter the filter + * @param justOnce the just once + * @return the write result + */ public WriteResult remove(Filter filter, boolean justOnce) { return writeOperations.remove(filter, justOnce); } - public DocumentCursor find() { - return readOperations.find(); - } - - public DocumentCursor find(Filter filter) { - return readOperations.find(filter); + /** + * Finds documents using filter. + * + * @param filter the filter + * @return the document cursor + */ + public DocumentCursor find(Filter filter, FindOptions findOptions) { + return readOperations.find(filter, findOptions); } + /** + * Gets document by id. + * + * @param nitriteId the nitrite id + * @return the by id + */ public Document getById(NitriteId nitriteId) { return readOperations.getById(nitriteId); } + /** + * Drops the collection. + */ public void dropCollection() { indexOperations.dropAllIndices(); dropNitriteMap(); } + /** + * Gets the size of the collection. + * + * @return the size + */ public long getSize() { return nitriteMap.size(); } + /** + * Gets the additional attributes for the collection. + * + * @return the attributes + */ public Attributes getAttributes() { return nitriteMap != null ? nitriteMap.getAttributes() : null; } + /** + * Sets additional attributes in the collection. + * + * @param attributes the attributes + */ public void setAttributes(Attributes attributes) { nitriteMap.setAttributes(attributes); } @@ -141,37 +267,40 @@ public void close() { if (indexOperations != null) { indexOperations.close(); } + nitriteMap.close(); } - private void init() { - this.indexOperations = new IndexOperations(nitriteConfig, nitriteMap, eventBus); - this.readOperations = new ReadOperations(collectionName, nitriteConfig, nitriteMap, indexOperations); - this.writeOperations = new WriteOperations(indexOperations, readOperations, - nitriteMap, eventBus); + private void initialize() { + this.processorChain = new ProcessorChain(); + this.indexOperations = new IndexOperations(collectionName, nitriteConfig, nitriteMap, eventBus); + this.readOperations = new ReadOperations(collectionName, indexOperations, + nitriteConfig, nitriteMap, processorChain); + + DocumentIndexWriter indexWriter = new DocumentIndexWriter(nitriteConfig, indexOperations); + this.writeOperations = new WriteOperations(indexWriter, readOperations, + nitriteMap, eventBus, processorChain); } private void dropNitriteMap() { - NitriteMap catalogueMap = nitriteMap.getStore().openMap(COLLECTION_CATALOG, String.class, Document.class); - for (Pair entry : catalogueMap.entries()) { - String catalogue = entry.getFirst(); - Document document = entry.getSecond(); - - Set bin = new HashSet<>(); - boolean foundKey = false; - for (String field : document.getFields()) { - if (field.equals(nitriteMap.getName())) { - foundKey = true; - bin.add(field); - } - } - - for (String field : bin) { - document.remove(field); - } - catalogueMap.put(catalogue, document); - - if (foundKey) break; - } + // remove the collection name from the catalog + StoreCatalog catalog = nitriteMap.getStore().getCatalog(); + catalog.remove(nitriteMap.getName()); + + // drop the map nitriteMap.drop(); } + + private void doProcess(Processor processor) { + for (Document document : find(Filter.ALL, null)) { + Document processed = processor.processBeforeWrite(document); + update(createUniqueFilter(document), processed, updateOptions(false)); + } + } + + private void undoProcess(Processor processor) { + for (Document document : find(Filter.ALL, null)) { + Document processed = processor.processAfterRead(document); + update(createUniqueFilter(document), processed, updateOptions(false)); + } + } } diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/operation/DocumentCursorImpl.java b/nitrite/src/main/java/org/dizitart/no2/collection/operation/DocumentCursorImpl.java deleted file mode 100644 index f6ca0a4de..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/collection/operation/DocumentCursorImpl.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection.operation; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.*; -import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.exceptions.ValidationException; - -import java.text.Collator; -import java.util.Collections; -import java.util.Iterator; - -/** - * @author Anindya Chatterjee. - */ -class DocumentCursorImpl implements DocumentCursor { - private final RecordStream> recordStream; - - DocumentCursorImpl(RecordStream> recordStream) { - this.recordStream = recordStream; - } - - @Override - public DocumentCursor sort(String field, SortOrder sortOrder, Collator collator, NullOrder nullOrder) { - return new DocumentCursorImpl(new SortedDocumentCursor(field, sortOrder, collator, - nullOrder, recordStream)); - } - - @Override - public DocumentCursor skipLimit(long skip, long limit) { - return new DocumentCursorImpl(new BoundedDocumentStream(recordStream, skip, limit)); - } - - @Override - public RecordStream project(Document projection) { - validateProjection(projection); - return new ProjectedDocumentStream(recordStream, projection); - } - - @Override - public RecordStream join(DocumentCursor foreignCursor, Lookup lookup) { - return new JoinedDocumentStream(recordStream, foreignCursor, lookup); - } - - @Override - public Iterator iterator() { - Iterator> iterator = recordStream == null ? Collections.emptyIterator() - : recordStream.iterator(); - return new DocumentCursorIterator(iterator); - } - - private void validateProjection(Document projection) { - for (Pair kvp : projection) { - validateKeyValuePair(kvp); - } - } - - private void validateKeyValuePair(Pair kvp) { - if (kvp.getSecond() != null) { - if (!(kvp.getSecond() instanceof Document)) { - throw new ValidationException("projection contains non-null values"); - } else { - validateProjection((Document) kvp.getSecond()); - } - } - } - - private static class DocumentCursorIterator implements Iterator { - private final Iterator> iterator; - - DocumentCursorIterator(Iterator> iterator) { - this.iterator = iterator; - } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public Document next() { - Pair next = iterator.next(); - Document document = next.getSecond(); - if (document != null) { - return document.clone(); - } - return null; - } - - @Override - public void remove() { - throw new InvalidOperationException("remove on cursor is not supported"); - } - } -} diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/operation/DocumentIndexWriter.java b/nitrite/src/main/java/org/dizitart/no2/collection/operation/DocumentIndexWriter.java new file mode 100644 index 000000000..394cfb706 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/collection/operation/DocumentIndexWriter.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2017-2020. Nitrite author or authors. + * + * Licensed 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.dizitart.no2.collection.operation; + +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.FieldValues; +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.common.util.DocumentUtils; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.NitriteIndexer; + +import java.util.Collection; + +/** + * + * @since 4.0 + * @author Anindya Chatterjee + */ +class DocumentIndexWriter { + private final NitriteConfig nitriteConfig; + private final IndexOperations indexOperations; + + DocumentIndexWriter(NitriteConfig nitriteConfig, + IndexOperations indexOperations) { + this.nitriteConfig = nitriteConfig; + this.indexOperations = indexOperations; + } + + void writeIndexEntry(Document document) { + Collection indexEntries = indexOperations.listIndexes(); + if (indexEntries != null) { + for (IndexDescriptor indexDescriptor : indexEntries) { + String indexType = indexDescriptor.getIndexType(); + NitriteIndexer nitriteIndexer = nitriteConfig.findIndexer(indexType); + + writeIndexEntryInternal(indexDescriptor, document, nitriteIndexer); + } + } + } + + void removeIndexEntry(Document document) { + Collection indexEntries = indexOperations.listIndexes(); + if (indexEntries != null) { + for (IndexDescriptor indexDescriptor : indexEntries) { + String indexType = indexDescriptor.getIndexType(); + NitriteIndexer nitriteIndexer = nitriteConfig.findIndexer(indexType); + + removeIndexEntryInternal(indexDescriptor, document, nitriteIndexer); + } + } + } + + void updateIndexEntry(Document oldDocument, Document newDocument) { + Collection indexEntries = indexOperations.listIndexes(); + if (indexEntries != null) { + for (IndexDescriptor indexDescriptor : indexEntries) { + String indexType = indexDescriptor.getIndexType(); + NitriteIndexer nitriteIndexer = nitriteConfig.findIndexer(indexType); + + removeIndexEntryInternal(indexDescriptor, oldDocument, nitriteIndexer); + writeIndexEntryInternal(indexDescriptor, newDocument, nitriteIndexer); + } + } + } + + private void writeIndexEntryInternal(IndexDescriptor indexDescriptor, Document document, + NitriteIndexer nitriteIndexer) { + if (indexDescriptor != null) { + Fields fields = indexDescriptor.getIndexFields(); + FieldValues fieldValues = DocumentUtils.getValues(document, fields); + + // if dirty index and currently indexing is not running, rebuild + if (indexOperations.shouldRebuildIndex(fields)) { + // rebuild will also take care of the current document + indexOperations.buildIndex(indexDescriptor, true); + } else if (nitriteIndexer != null) { + nitriteIndexer.writeIndexEntry(fieldValues, indexDescriptor, nitriteConfig); + } + } + } + + private void removeIndexEntryInternal(IndexDescriptor indexDescriptor, Document document, + NitriteIndexer nitriteIndexer) { + if (indexDescriptor != null) { + Fields fields = indexDescriptor.getIndexFields(); + FieldValues fieldValues = DocumentUtils.getValues(document, fields); + + // if dirty index and currently indexing is not running, rebuild + if (indexOperations.shouldRebuildIndex(fields)) { + // rebuild will also take care of the current document + indexOperations.buildIndex(indexDescriptor, true); + } else if (nitriteIndexer != null) { + nitriteIndexer.removeIndexEntry(fieldValues, indexDescriptor, nitriteConfig); + } + } + } + +} diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/operation/FilteredRecordStream.java b/nitrite/src/main/java/org/dizitart/no2/collection/operation/FilteredRecordStream.java deleted file mode 100644 index 8adeafbed..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/collection/operation/FilteredRecordStream.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection.operation; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.filters.Filter; - -import java.util.Collections; -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * @author Anindya Chatterjee. - */ -class FilteredRecordStream implements RecordStream> { - private final RecordStream> recordStream; - private final Filter filter; - - FilteredRecordStream(RecordStream> recordStream, Filter filter) { - this.recordStream = recordStream; - this.filter = filter; - } - - @Override - public Iterator> iterator() { - Iterator> iterator = recordStream == null ? Collections.emptyIterator() - : recordStream.iterator(); - return new FilteredIterator(iterator, filter); - } - - static class FilteredIterator implements Iterator> { - private final Iterator> iterator; - private final Filter filter; - private Pair nextPair; - private boolean nextPairSet = false; - - public FilteredIterator(Iterator> iterator, Filter filter) { - this.iterator = iterator; - this.filter = filter; - } - - @Override - public boolean hasNext() { - return nextPairSet || setNextId(); - } - - @Override - public Pair next() { - if (!nextPairSet && !setNextId()) { - throw new NoSuchElementException(); - } - nextPairSet = false; - return nextPair; - } - - @Override - public void remove() { - if (nextPairSet) { - throw new InvalidOperationException("remove operation cannot be called here"); - } - iterator.remove(); - } - - private boolean setNextId() { - while (iterator.hasNext()) { - final Pair pair = iterator.next(); - if (filter.apply(pair)) { - nextPair = pair; - nextPairSet = true; - return true; - } - } - return false; - } - } - -} diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/operation/FindOptimizer.java b/nitrite/src/main/java/org/dizitart/no2/collection/operation/FindOptimizer.java new file mode 100644 index 000000000..58b129016 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/collection/operation/FindOptimizer.java @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.collection.operation; + +import org.dizitart.no2.collection.FindOptions; +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.filters.*; +import org.dizitart.no2.index.IndexDescriptor; + +import java.util.*; + +import static org.dizitart.no2.common.Constants.DOC_ID; +import static org.dizitart.no2.common.util.Iterables.firstOrNull; +import static org.dizitart.no2.filters.Filter.and; +import static org.dizitart.no2.filters.Filter.or; + + +/** + * + * @since 4.0 + * @author Anindya Chatterjee + */ +class FindOptimizer { + + public FindPlan optimize(Filter filter, + FindOptions findOptions, + Collection indexDescriptors) { + FindPlan findPlan = createFilterPlan(indexDescriptors, filter); + readSortOption(findOptions, findPlan); + readLimitOption(findOptions, findPlan); + + if (findOptions != null) { + findPlan.setCollator(findOptions.collator()); + } + return findPlan; + } + + private FindPlan createFilterPlan(Collection indexDescriptors, Filter filter) { + if (filter instanceof AndFilter) { + List filters = flattenAndFilter((AndFilter) filter); + return createAndPlan(indexDescriptors, filters); + } else if (filter instanceof OrFilter) { + return createOrPlan(indexDescriptors, ((OrFilter) filter).getFilters()); + } else { + List filters = Collections.singletonList(filter); + return createAndPlan(indexDescriptors, filters); + } + } + + private List flattenAndFilter(AndFilter andFilter) { + List flattenedFilters = new ArrayList<>(); + if (andFilter != null) { + for (Filter filter : andFilter.getFilters()) { + if (filter instanceof AndFilter) { + List filters = flattenAndFilter((AndFilter) filter); + flattenedFilters.addAll(filters); + } else { + flattenedFilters.add(filter); + } + } + } + return flattenedFilters; + } + + private FindPlan createOrPlan(Collection indexDescriptors, List filters) { + FindPlan findPlan = new FindPlan(); + + Set flattenedFilter = new HashSet<>(); + + // flatten the or filter + for (Filter filter : filters) { + if (filter instanceof OrFilter) { + flattenedFilter.addAll(((OrFilter) filter).getFilters()); + } else { + flattenedFilter.add(filter); + } + } + + for (Filter filter : flattenedFilter) { + FindPlan subPlan = createFilterPlan(indexDescriptors, filter); + findPlan.getSubPlans().add(subPlan); + } + + // check if all sub plan have index support + for (FindPlan plan : findPlan.getSubPlans()) { + if (plan.getIndexDescriptor() == null) { + // if one of the sub plan doesn't have any index support + // then it can not be optimized, instead the + // original filter should be set as coll-scan filter + // for the parent plan + findPlan.getSubPlans().clear(); + // set the original or filter as coll scan filter + findPlan.setCollectionScanFilter(or(filters.toArray(new Filter[0]))); + return findPlan; + } + } + return findPlan; + } + + private FindPlan createAndPlan(Collection indexDescriptors, List filters) { + FindPlan findPlan = new FindPlan(); + Set indexScanFilters = new LinkedHashSet<>(); + Set columnScanFilters = new LinkedHashSet<>(); + + // find out set id filter (if any) + planForIdFilter(findPlan, filters); + + // find out if there are any index only filter with index + planForIndexOnlyFilters(findPlan, indexScanFilters, indexDescriptors, filters); + + // if no id filter found or no index only filter found, scan for matching index + if (findPlan.getByIdFilter() == null && indexScanFilters.isEmpty()) { + planForIndexScanningFilters(findPlan, indexScanFilters, indexDescriptors, filters); + } + + // plan for column scan filters + planForCollectionScanningFilters(findPlan, indexScanFilters, columnScanFilters, filters); + + IndexScanFilter indexScanFilter; + if (indexScanFilters.size() == 1) { + indexScanFilter = new IndexScanFilter(Collections.singletonList(firstOrNull(indexScanFilters))); + findPlan.setIndexScanFilter(indexScanFilter); + } else if (indexScanFilters.size() > 1) { + indexScanFilter = new IndexScanFilter(indexScanFilters); + findPlan.setIndexScanFilter(indexScanFilter); + } + + if (columnScanFilters.size() == 1) { + findPlan.setCollectionScanFilter(firstOrNull(columnScanFilters)); + } else if (columnScanFilters.size() > 1) { + Filter andFilter = and(columnScanFilters.toArray(new Filter[0])); + findPlan.setCollectionScanFilter(andFilter); + } + + return findPlan; + } + + private void planForIdFilter(FindPlan findPlan, List filters) { + for (Filter filter : filters) { + if (filter instanceof EqualsFilter) { + EqualsFilter equalsFilter = (EqualsFilter) filter; + + // handle byId filter specially + if (equalsFilter.getField().equals(DOC_ID)) { + findPlan.setByIdFilter(equalsFilter); + } + break; + } + } + } + + private void planForIndexOnlyFilters(FindPlan findPlan, Set indexScanFilters, + Collection indexDescriptors, List filters) { + // find out if there are any filter which does not support covered queries + List indexOnlyFilters = new ArrayList<>(); + for (Filter filter : filters) { + if (filter instanceof IndexOnlyFilter) { + IndexOnlyFilter indexScanFilter = (IndexOnlyFilter) filter; + if (isCompatibleFilter(indexOnlyFilters, indexScanFilter)) { + // if filter is compatible with already identified index only filter then add + indexOnlyFilters.add(indexScanFilter); + } else { + throw new FilterException("a query can not have multiple index only filters"); + } + } + } + + // populate index descriptor for the index only filters + if (!indexOnlyFilters.isEmpty()) { + + // get any index only filter from the set + IndexOnlyFilter anyFilter = indexOnlyFilters.get(0); + for (IndexDescriptor indexDescriptor : indexDescriptors) { + + // check the index type match between filter and index descriptor + if (anyFilter.supportedIndexType().equals(indexDescriptor.getIndexType())) { + // choose the index descriptor and filters + findPlan.setIndexDescriptor(indexDescriptor); + indexScanFilters.addAll(indexOnlyFilters); + break; + } + } + + if (findPlan.getIndexDescriptor() == null) { + throw new FilterException(anyFilter.getField() + " is not indexed with " + + anyFilter.supportedIndexType() + " index"); + } + } + } + + private boolean isCompatibleFilter(List indexOnlyFilters, IndexOnlyFilter filter) { + if (indexOnlyFilters.isEmpty()) { + return true; + } else { + IndexOnlyFilter comparableFilter = indexOnlyFilters.get(0); + return comparableFilter.canBeGrouped(filter); + } + } + + private void planForIndexScanningFilters(FindPlan findPlan, Set indexScanFilters, + Collection indexDescriptors, List filters) { + // descending sort based on cardinality of indices, consider the higher cardinality index first + NavigableMap> indexFilterMap = new TreeMap<>(Collections.reverseOrder()); + + for (IndexDescriptor indexDescriptor : indexDescriptors) { + List fieldNames = indexDescriptor.getIndexFields().getFieldNames(); + + List indexedFilters = new ArrayList<>(); + for (String fieldName : fieldNames) { + boolean matchFound = false; + for (Filter filter : filters) { + if (filter instanceof ComparableFilter) { + String filterFieldName = ((ComparableFilter) filter).getField(); + if (filterFieldName.equals(fieldName)) { + indexedFilters.add((ComparableFilter) filter); + matchFound = true; + break; + } + } + } + + if (!matchFound) { + // match not found, so can't consider this index + break; + } + } + + if (!indexedFilters.isEmpty()) { + indexFilterMap.put(indexDescriptor, indexedFilters); + } + } + + for (Map.Entry> entry : indexFilterMap.entrySet()) { + // consider the filter combination if it encompasses more fields + // than the previously selected filter + if (entry.getValue().size() > indexScanFilters.size()) { + // maintain the order in set + indexScanFilters.addAll(entry.getValue()); + findPlan.setIndexDescriptor(entry.getKey()); + } + } + } + + private void planForCollectionScanningFilters(FindPlan findPlan, Set indexScanFilters, + Set columnScanFilters, List filters) { + for (Filter filter : filters) { + // ignore the elected filters for index scan and + // insert rest of the filters for column scan + // NOTE: for byId filter, index scan filters will always be empty + if (!(filter instanceof ComparableFilter) || !indexScanFilters.contains(filter)) { + // ignore the byId filter (if any) for column scan + if (filter != findPlan.getByIdFilter()) { + columnScanFilters.add(filter); + } + } + } + + // validate whether column scanning is supported for each filter, + // if there is no index scan available + if (indexScanFilters.isEmpty()) { + validateCollectionScanFilters(columnScanFilters); + } + } + + private void validateCollectionScanFilters(Collection filters) { + for (Filter filter : filters) { + if (filter instanceof IndexOnlyFilter) { + throw new FilterException("collection scan is not supported for the filter " + filter); + } else if (filter instanceof TextFilter) { + throw new FilterException(((TextFilter) filter).getField() + " is not full-text indexed"); + } + } + } + + private void readSortOption(FindOptions findOptions, FindPlan findPlan) { + IndexDescriptor indexDescriptor = findPlan.getIndexDescriptor(); + if (findOptions != null && findOptions.orderBy() != null) { + // get sort spec for find + List> findSortSpec = findOptions.orderBy().getSortingOrders(); + + if (indexDescriptor != null) { + // get index field names + List indexedFieldNames = indexDescriptor.getIndexFields().getFieldNames(); + + boolean canUseIndex = false; + Map indexScanOrder = new HashMap<>(); + + if (indexedFieldNames.size() >= findSortSpec.size()) { + // if all fields of the sort spec is covered by index, then only + // sorting can take help of index + + int length = findSortSpec.size(); + for (int i = 0; i < length; i++) { + String indexFieldName = indexedFieldNames.get(i); + Pair findPair = findSortSpec.get(i); + if (!indexFieldName.equals(findPair.getFirst())) { + // field mismatch in sort spec, can't use index for sorting + canUseIndex = false; + break; + } else { + canUseIndex = true; + boolean reverseScan = false; + + SortOrder findSortOrder = findPair.getSecond(); + if (findSortOrder != SortOrder.Ascending) { + // if sort order is different, reverse scan in index + reverseScan = true; + } + + // add to index scan order + indexScanOrder.put(indexFieldName, reverseScan); + } + } + } + + if (canUseIndex) { + findPlan.setIndexScanOrder(indexScanOrder); + } else { + findPlan.setBlockingSortOrder(findSortSpec); + } + } else { + // no find options, so consider the index sorting order + findPlan.setBlockingSortOrder(findSortSpec); + } + } + } + + private void readLimitOption(FindOptions findOptions, FindPlan findPlan) { + if (findOptions != null) { + findPlan.setLimit(findOptions.limit()); + findPlan.setSkip(findOptions.skip()); + } + } + +} diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/operation/IndexManager.java b/nitrite/src/main/java/org/dizitart/no2/collection/operation/IndexManager.java new file mode 100644 index 000000000..2464048e2 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/collection/operation/IndexManager.java @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.collection.operation; + +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.IndexMeta; +import org.dizitart.no2.index.NitriteIndexer; +import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.store.NitriteStore; + +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.dizitart.no2.common.util.IndexUtils.deriveIndexMapName; +import static org.dizitart.no2.common.util.IndexUtils.deriveIndexMetaMapName; + +/** + * Represents the index manager for a collection. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +public class IndexManager implements AutoCloseable { + private final NitriteConfig nitriteConfig; + private final NitriteStore nitriteStore; + private final String collectionName; + private final NitriteMap indexMetaMap; + private Collection indexDescriptorCache; + + /** + * Instantiates a new {@link IndexManager}. + * + * @param collectionName the collection name + * @param nitriteConfig the nitrite config + */ + public IndexManager(String collectionName, NitriteConfig nitriteConfig) { + this.collectionName = collectionName; + this.nitriteConfig = nitriteConfig; + this.nitriteStore = nitriteConfig.getNitriteStore(); + this.indexMetaMap = getIndexMetaMap(); + initialize(); + } + + /** + * Checks if an index descriptor already exists on the fields. + * + * @param fields the fields + * @return the boolean + */ + public boolean hasIndexDescriptor(Fields fields) { + return !findMatchingIndexDescriptors(fields).isEmpty(); + } + + /** + * Gets all defined index descriptors for the collection. + * + * @return the index descriptors + */ + public Collection getIndexDescriptors() { + if (indexDescriptorCache == null) { + indexDescriptorCache = listIndexDescriptors(); + } + return indexDescriptorCache; + } + + public Collection findMatchingIndexDescriptors(Fields fields) { + List indexDescriptors = new ArrayList<>(); + + for (IndexDescriptor indexDescriptor : getIndexDescriptors()) { + if (indexDescriptor.getIndexFields().startsWith(fields)) { + indexDescriptors.add(indexDescriptor); + } + } + + return indexDescriptors; + } + + public IndexDescriptor findExactIndexDescriptor(Fields fields) { + IndexMeta meta = indexMetaMap.get(fields); + if (meta != null) { + return meta.getIndexDescriptor(); + } + return null; + } + + @Override + public void close() { + // close all index maps + Iterable indexMetas = indexMetaMap.values(); + for (IndexMeta indexMeta : indexMetas) { + if (indexMeta != null && indexMeta.getIndexDescriptor() != null) { + String indexMapName = indexMeta.getIndexMap(); + NitriteMap indexMap = nitriteStore.openMap(indexMapName, Object.class, Object.class); + indexMap.close(); + } + } + + // close index meta + indexMetaMap.close(); + } + + /** + * Is dirty index boolean. + * + * @param fields the fields + * @return the boolean + */ + boolean isDirtyIndex(Fields fields) { + IndexMeta meta = indexMetaMap.get(fields); + return meta != null && meta.getIsDirty().get(); + } + + /** + * List index descriptors collection. + * + * @return the collection + */ + Collection listIndexDescriptors() { + Set indexSet = new LinkedHashSet<>(); + Iterable iterable = indexMetaMap.values(); + for (IndexMeta indexMeta : iterable) { + indexSet.add(indexMeta.getIndexDescriptor()); + } + return Collections.unmodifiableSet(indexSet); + } + + /** + * Create index descriptor index descriptor. + * + * @param fields the fields + * @param indexType the index type + * @return the index descriptor + */ + IndexDescriptor createIndexDescriptor(Fields fields, String indexType) { + validateIndexRequest(fields, indexType); + IndexDescriptor index = new IndexDescriptor(indexType, fields, collectionName); + + IndexMeta indexMeta = new IndexMeta(); + indexMeta.setIndexDescriptor(index); + indexMeta.setIsDirty(new AtomicBoolean(false)); + indexMeta.setIndexMap(deriveIndexMapName(index)); + + indexMetaMap.put(fields, indexMeta); + + updateIndexDescriptorCache(); + return index; + } + + /** + * Drop index descriptor. + * + * @param fields the fields + */ + void dropIndexDescriptor(Fields fields) { + IndexMeta meta = indexMetaMap.get(fields); + if (meta != null && meta.getIndexDescriptor() != null) { + String indexMapName = meta.getIndexMap(); + NitriteMap indexMap = nitriteStore.openMap(indexMapName, Object.class, Object.class); + indexMap.drop(); + } + + indexMetaMap.remove(fields); + updateIndexDescriptorCache(); + } + + void dropIndexMeta() { + indexMetaMap.clear(); + indexMetaMap.drop(); + } + + /** + * Begin indexing. + * + * @param fields the fields + */ + void beginIndexing(Fields fields) { + markDirty(fields, true); + } + + /** + * End indexing. + * + * @param fields the fields + */ + void endIndexing(Fields fields) { + markDirty(fields, false); + } + + private void initialize() { + updateIndexDescriptorCache(); + } + + private void markDirty(Fields fields, boolean dirty) { + IndexMeta meta = indexMetaMap.get(fields); + if (meta != null && meta.getIndexDescriptor() != null) { + meta.getIsDirty().set(dirty); + } + } + + private NitriteMap getIndexMetaMap() { + String mapName = deriveIndexMetaMapName(this.collectionName); + return this.nitriteStore.openMap(mapName, Fields.class, IndexMeta.class); + } + + private void updateIndexDescriptorCache() { + indexDescriptorCache = listIndexDescriptors(); + } + + private void validateIndexRequest(Fields fields, String indexType) { + NitriteIndexer indexer = nitriteConfig.findIndexer(indexType); + indexer.validateIndex(fields); + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/operation/IndexOperations.java b/nitrite/src/main/java/org/dizitart/no2/collection/operation/IndexOperations.java index aa51a8355..9d6dc9a45 100644 --- a/nitrite/src/main/java/org/dizitart/no2/collection/operation/IndexOperations.java +++ b/nitrite/src/main/java/org/dizitart/no2/collection/operation/IndexOperations.java @@ -1,19 +1,3 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection.operation; import org.dizitart.no2.NitriteConfig; @@ -22,275 +6,188 @@ import org.dizitart.no2.collection.events.CollectionEventInfo; import org.dizitart.no2.collection.events.CollectionEventListener; import org.dizitart.no2.collection.events.EventType; -import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.common.concurrent.ThreadPoolManager; +import org.dizitart.no2.common.FieldValues; +import org.dizitart.no2.common.Fields; import org.dizitart.no2.common.event.EventBus; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.common.util.DocumentUtils; import org.dizitart.no2.exceptions.IndexingException; -import org.dizitart.no2.index.IndexEntry; -import org.dizitart.no2.index.Indexer; -import org.dizitart.no2.store.IndexCatalog; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.NitriteIndexer; import org.dizitart.no2.store.NitriteMap; -import org.dizitart.no2.store.NitriteStore; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; -import static org.dizitart.no2.common.util.ValidationUtils.validateDocumentIndexField; +import static org.dizitart.no2.common.concurrent.ThreadPoolManager.runAsync; /** * @author Anindya Chatterjee */ class IndexOperations implements AutoCloseable { + private final String collectionName; private final NitriteConfig nitriteConfig; private final NitriteMap nitriteMap; private final EventBus, CollectionEventListener> eventBus; - private String collectionName; - private IndexCatalog indexCatalog; - private Map indexBuildRegistry; - private ExecutorService rebuildExecutor; + private final Map indexBuildTracker; + private IndexManager indexManager; - IndexOperations(NitriteConfig nitriteConfig, NitriteMap nitriteMap, + IndexOperations(String collectionName, NitriteConfig nitriteConfig, + NitriteMap nitriteMap, EventBus, CollectionEventListener> eventBus) { + this.collectionName = collectionName; this.nitriteConfig = nitriteConfig; this.nitriteMap = nitriteMap; this.eventBus = eventBus; - init(); + this.indexBuildTracker = new ConcurrentHashMap<>(); + this.indexManager = new IndexManager(collectionName, nitriteConfig); } @Override public void close() { - if (rebuildExecutor != null) { - this.rebuildExecutor.shutdown(); - } + indexManager.close(); } - void ensureIndex(String field, String indexType, boolean isAsync) { - IndexEntry indexEntry; - if (!hasIndexEntry(field)) { + void createIndex(Fields fields, String indexType) { + IndexDescriptor indexDescriptor = indexManager.findExactIndexDescriptor(fields); + if (indexDescriptor == null) { // if no index create index - indexEntry = indexCatalog.createIndexEntry(collectionName, field, indexType); + indexDescriptor = indexManager.createIndexDescriptor(fields, indexType); } else { // if index already there throw - throw new IndexingException("index already exists on " + field); + throw new IndexingException("index already exists on " + fields); } - rebuildIndex(indexEntry, isAsync); - } - - void writeIndex(Document document, NitriteId nitriteId) { - Collection indexEntries = listIndexes(); - if (indexEntries != null) { - for (IndexEntry indexEntry : indexEntries) { - String field = indexEntry.getField(); - String indexType = indexEntry.getIndexType(); - Indexer indexer = findIndexer(indexType); - - writeIndexEntry(field, document, nitriteId, indexer, indexEntry); - } - } - } - - void removeIndex(Document document, NitriteId nitriteId) { - Collection indexEntries = listIndexes(); - if (indexEntries != null) { - for (IndexEntry indexEntry : indexEntries) { - String field = indexEntry.getField(); - String indexType = indexEntry.getIndexType(); - Indexer indexer = findIndexer(indexType); - - removeIndexEntry(field, document, nitriteId, indexer, indexEntry); - } - } - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - void updateIndex(Document oldDocument, Document newDocument, NitriteId nitriteId) { - Collection indexEntries = listIndexes(); - if (indexEntries != null) { - for (IndexEntry indexEntry : indexEntries) { - String field = indexEntry.getField(); - Object newValue = newDocument.get(field); - Object oldValue = oldDocument.get(field); - - if (newValue == null) continue; - if (newValue instanceof Comparable && oldValue instanceof Comparable) { - if (((Comparable) newValue).compareTo(oldValue) == 0) continue; - } - - validateDocumentIndexField(newValue, field); - - if (indexCatalog.isDirtyIndex(collectionName, field) - && !getBuildFlag(field).get()) { - // rebuild will also take care of the current document - rebuildIndex(indexEntry, true); - } else { - String indexType = indexEntry.getIndexType(); - Indexer indexer = findIndexer(indexType); - indexer.updateIndex(nitriteMap, nitriteId, field, newValue, oldValue); - } - } - } + buildIndex(indexDescriptor, false); } // call to this method is already synchronized, only one thread per field // can access it only if rebuild is already not running for that field - void rebuildIndex(IndexEntry indexEntry, boolean isAsync) { - final String field = indexEntry.getField(); - if (getBuildFlag(field).compareAndSet(false, true)) { - if (isAsync) { - rebuildExecutor.submit(() -> buildIndexInternal(field, indexEntry)); - } else { - buildIndexInternal(field, indexEntry); - } + void buildIndex(IndexDescriptor indexDescriptor, boolean rebuild) { + final Fields fields = indexDescriptor.getIndexFields(); + if (getBuildFlag(fields).compareAndSet(false, true)) { + buildIndexInternal(indexDescriptor, rebuild); return; } - throw new IndexingException("indexing is already running on " + indexEntry.getField()); + throw new IndexingException("indexing is already running on " + indexDescriptor.getIndexFields()); } - void dropIndex(String field) { - if (getBuildFlag(field).get()) { - throw new IndexingException("cannot drop index as indexing is running on " + field); + void dropIndex(Fields fields) { + if (getBuildFlag(fields).get()) { + throw new IndexingException("cannot drop index as indexing is running on " + fields); } - IndexEntry indexEntry = findIndexEntry(field); - if (indexEntry != null) { - String indexType = indexEntry.getIndexType(); - Indexer indexer = findIndexer(indexType); - indexer.dropIndex(nitriteMap, field); - indexCatalog.dropIndexEntry(collectionName, field); - indexBuildRegistry.remove(field); + IndexDescriptor indexDescriptor = findIndexDescriptor(fields); + if (indexDescriptor != null) { + String indexType = indexDescriptor.getIndexType(); + NitriteIndexer nitriteIndexer = nitriteConfig.findIndexer(indexType); + nitriteIndexer.dropIndex(indexDescriptor, nitriteConfig); + + indexManager.dropIndexDescriptor(fields); + indexBuildTracker.remove(fields); } else { - throw new IndexingException(field + " is not indexed"); + throw new IndexingException(fields + " is not indexed"); } } void dropAllIndices() { - for (Map.Entry entry : indexBuildRegistry.entrySet()) { + for (Map.Entry entry : indexBuildTracker.entrySet()) { if (entry.getValue() != null && entry.getValue().get()) { throw new IndexingException("cannot drop index as indexing is running on " + entry.getKey()); } } - for (IndexEntry index : listIndexes()) { - dropIndex(index.getField()); + // we can drop all indices in parallel + List> futures = new ArrayList<>(); + for (IndexDescriptor index : listIndexes()) { + futures.add(runAsync(() -> dropIndex(index.getIndexFields()))); + } + + for (Future future : futures) { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + throw new IndexingException("failed to drop all indices", e); + } } - indexBuildRegistry.clear(); + + indexManager.dropIndexMeta(); + indexBuildTracker.clear(); + + // recreate index manager to discard old native resources + // special measure for RocksDB adapter + this.indexManager = new IndexManager(collectionName, nitriteConfig); } - boolean isIndexing(String field) { + boolean isIndexing(Fields field) { // has an index will only return true, if there is an index on // the value and indexing is not running on it - return indexCatalog.hasIndexEntry(collectionName, field) + return indexManager.hasIndexDescriptor(field) && getBuildFlag(field).get(); } - boolean hasIndexEntry(String field) { - return indexCatalog.hasIndexEntry(collectionName, field); + boolean hasIndexEntry(Fields field) { + return indexManager.hasIndexDescriptor(field); } - Collection listIndexes() { - return indexCatalog.listIndexEntries(collectionName); + Collection listIndexes() { + return indexManager.getIndexDescriptors(); } - IndexEntry findIndexEntry(String field) { - return indexCatalog.findIndexEntry(collectionName, field); + IndexDescriptor findIndexDescriptor(Fields field) { + return indexManager.findExactIndexDescriptor(field); } - Indexer findIndexer(String indexType) { - Indexer indexer = nitriteConfig.findIndexer(indexType); - if (indexer != null) { - return indexer; - } - throw new IndexingException("no indexer found for index type " + indexType); + AtomicBoolean getBuildFlag(Fields field) { + AtomicBoolean flag = indexBuildTracker.get(field); + if (flag != null) return flag; + + flag = new AtomicBoolean(false); + indexBuildTracker.put(field, flag); + return flag; } - private void init() { - NitriteStore nitriteStore = nitriteConfig.getNitriteStore(); - this.indexCatalog = nitriteStore.getIndexCatalog(); - this.collectionName = nitriteMap.getName(); - this.indexBuildRegistry = new ConcurrentHashMap<>(); - this.rebuildExecutor = ThreadPoolManager.workerPool(); + boolean shouldRebuildIndex(Fields fields) { + return indexManager.isDirtyIndex(fields) && !getBuildFlag(fields).get(); } - private void buildIndexInternal(final String field, final IndexEntry indexEntry) { + private void buildIndexInternal(IndexDescriptor indexDescriptor, boolean rebuild) { + Fields fields = indexDescriptor.getIndexFields(); try { - alert(EventType.IndexStart, field); + alert(EventType.IndexStart, fields); // first put dirty marker - indexCatalog.beginIndexing(collectionName, field); + indexManager.beginIndexing(fields); - String indexType = indexEntry.getIndexType(); - Indexer indexer = findIndexer(indexType); + String indexType = indexDescriptor.getIndexType(); + NitriteIndexer nitriteIndexer = nitriteConfig.findIndexer(indexType); + + // if rebuild drop existing index + if (rebuild) { + nitriteIndexer.dropIndex(indexDescriptor, nitriteConfig); + } - // re-create the index for the values of the field from document for (Pair entry : nitriteMap.entries()) { Document document = entry.getSecond(); - if (document.getFields().contains(field)) { - // remove old values if exists - removeIndexEntry(field, entry.getSecond(), entry.getFirst(), indexer, indexEntry); - - // re-create new entry - writeIndexEntry(field, entry.getSecond(), entry.getFirst(), indexer, indexEntry); - } + FieldValues fieldValues = DocumentUtils.getValues(document, indexDescriptor.getIndexFields()); + nitriteIndexer.writeIndexEntry(fieldValues, indexDescriptor, nitriteConfig); } } finally { // remove dirty marker to denote indexing completed successfully // if dirty marker is found in any index, it needs to be rebuild - indexCatalog.endIndexing(collectionName, field); - getBuildFlag(field).set(false); - alert(EventType.IndexEnd, field); + indexManager.endIndexing(fields); + getBuildFlag(fields).set(false); + alert(EventType.IndexEnd, fields); } } - private void writeIndexEntry(String field, Document document, NitriteId nitriteId, - Indexer indexer, IndexEntry indexEntry) { - if (indexEntry != null) { - Object fieldValue = document.get(field); - validateDocumentIndexField(fieldValue, field); - - // if dirty index and currently indexing is not running, rebuild - if (indexCatalog.isDirtyIndex(collectionName, field) - && !getBuildFlag(field).get()) { - // rebuild will also take care of the current document - rebuildIndex(indexEntry, true); - } else if (indexer != null) { - indexer.writeIndex(nitriteMap, nitriteId, field, fieldValue); - } - } - } - - private void removeIndexEntry(String field, Document document, NitriteId nitriteId, - Indexer indexer, IndexEntry indexEntry) { - if (indexEntry != null) { - Object fieldValue = document.get(field); - if (fieldValue == null) return; - - validateDocumentIndexField(fieldValue, field); - - // if dirty index and currently indexing is not running, rebuild - if (indexCatalog.isDirtyIndex(collectionName, field) - && !getBuildFlag(field).get()) { - // rebuild will also take care of the current document - rebuildIndex(indexEntry, true); - } else if (indexer != null) { - indexer.removeIndex(nitriteMap, nitriteId, field, fieldValue); - } - } - } - - private AtomicBoolean getBuildFlag(String field) { - AtomicBoolean flag = indexBuildRegistry.get(field); - if (flag != null) return flag; - - flag = new AtomicBoolean(false); - indexBuildRegistry.put(field, flag); - return flag; - } - - private void alert(EventType eventType, String field) { - CollectionEventInfo eventInfo = new CollectionEventInfo<>(); + private void alert(EventType eventType, Fields field) { + CollectionEventInfo eventInfo = new CollectionEventInfo<>(); eventInfo.setItem(field); eventInfo.setTimestamp(System.currentTimeMillis()); eventInfo.setEventType(eventType); diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/operation/IndexedStream.java b/nitrite/src/main/java/org/dizitart/no2/collection/operation/IndexedStream.java deleted file mode 100644 index a9e214b43..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/collection/operation/IndexedStream.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2019-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection.operation; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.filters.IndexAwareFilter; -import org.dizitart.no2.store.NitriteMap; - -import java.util.Iterator; -import java.util.Set; - -/** - * @author Anindya Chatterjee - */ -class IndexedStream implements RecordStream> { - private final Set nitriteIds; - private final NitriteMap nitriteMap; - - IndexedStream(IndexAwareFilter indexAwareFilter, - NitriteMap nitriteMap) { - this.nitriteMap = nitriteMap; - - nitriteIds = indexAwareFilter.getOnIdField() - ? indexAwareFilter.cachedIds(nitriteMap) - : indexAwareFilter.cachedIndexedIds(); - } - - @Override - public Iterator> iterator() { - return new IndexedStreamIterator(nitriteIds.iterator(), nitriteMap); - } - - static class IndexedStreamIterator implements Iterator> { - private final Iterator iterator; - private final NitriteMap nitriteMap; - - IndexedStreamIterator(Iterator iterator, - NitriteMap nitriteMap) { - this.iterator = iterator; - this.nitriteMap = nitriteMap; - } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public Pair next() { - NitriteId id = iterator.next(); - Document document = nitriteMap.get(id); - return new Pair<>(id, document); - } - } -} diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/operation/JoinedDocumentStream.java b/nitrite/src/main/java/org/dizitart/no2/collection/operation/JoinedDocumentStream.java deleted file mode 100644 index 886d0496e..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/collection/operation/JoinedDocumentStream.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection.operation; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.common.Lookup; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -import static org.dizitart.no2.common.util.ObjectUtils.deepEquals; - -/** - * @author Anindya Chatterjee. - */ -class JoinedDocumentStream implements RecordStream { - private final RecordStream> recordStream; - private final DocumentCursor foreignCursor; - private final Lookup lookup; - - JoinedDocumentStream(RecordStream> recordStream, - DocumentCursor foreignCursor, - Lookup lookup) { - this.recordStream = recordStream; - this.foreignCursor = foreignCursor; - this.lookup = lookup; - } - - - @Override - public Iterator iterator() { - Iterator> iterator = recordStream == null ? Collections.emptyIterator() - : recordStream.iterator(); - return new JoinedDocumentIterator(iterator); - } - - @Override - public String toString() { - return toList().toString(); - } - - private class JoinedDocumentIterator implements Iterator { - private final Iterator> iterator; - - JoinedDocumentIterator(Iterator> iterator) { - this.iterator = iterator; - } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public Document next() { - Pair next = iterator.next(); - Document document = next.getSecond(); - if (document != null) { - return join(document.clone(), foreignCursor, lookup); - } - return null; - } - - @Override - public void remove() { - throw new InvalidOperationException("remove on a cursor is not supported"); - } - - private Document join(Document localDocument, DocumentCursor foreignCursor, Lookup lookup) { - Object localObject = localDocument.get(lookup.getLocalField()); - if (localObject == null) return localDocument; - Set target = new HashSet<>(); - - for (Document foreignDocument : foreignCursor) { - Object foreignObject = foreignDocument.get(lookup.getForeignField()); - if (foreignObject != null) { - if (deepEquals(foreignObject, localObject)) { - target.add(foreignDocument); - } - } - } - if (!target.isEmpty()) { - localDocument.put(lookup.getTargetField(), target); - } - return localDocument; - } - } -} - diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/operation/ProjectedDocumentStream.java b/nitrite/src/main/java/org/dizitart/no2/collection/operation/ProjectedDocumentStream.java deleted file mode 100644 index 26c58749c..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/collection/operation/ProjectedDocumentStream.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection.operation; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; - -import java.util.Collections; -import java.util.Iterator; - -/** - * @author Anindya Chatterjee. - */ -class ProjectedDocumentStream implements RecordStream { - private final RecordStream> recordStream; - private final Document projection; - - public ProjectedDocumentStream(RecordStream> recordStream, - Document projection) { - this.recordStream = recordStream; - this.projection = projection; - } - - @Override - public Iterator iterator() { - Iterator> iterator = recordStream == null ? Collections.emptyIterator() - : recordStream.iterator(); - return new ProjectedDocumentIterator(iterator); - } - - @Override - public String toString() { - return toList().toString(); - } - - private class ProjectedDocumentIterator implements Iterator { - private final Iterator> iterator; - private Document nextElement = null; - - ProjectedDocumentIterator(Iterator> iterator) { - this.iterator = iterator; - nextMatch(); - } - - @Override - public boolean hasNext() { - return nextElement != null; - } - - @Override - public Document next() { - Document returnValue = nextElement.clone(); - nextMatch(); - return returnValue; - } - - private void nextMatch() { - while (iterator.hasNext()) { - Pair next = iterator.next(); - Document document = next.getSecond(); - if (document != null) { - Document projected = project(document.clone()); - if (projected != null) { - nextElement = projected; - return; - } - } - } - - nextElement = null; - } - - @Override - public void remove() { - throw new InvalidOperationException("remove on a cursor is not supported"); - } - - private Document project(Document original) { - if (projection == null) return original; - Document result = original.clone(); - - for (Pair pair : original) { - if (!projection.containsKey(pair.getFirst())) { - result.remove(pair.getFirst()); - } - } - return result; - } - } -} - diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/operation/ReadOperations.java b/nitrite/src/main/java/org/dizitart/no2/collection/operation/ReadOperations.java index e7eebbf65..4f7411feb 100644 --- a/nitrite/src/main/java/org/dizitart/no2/collection/operation/ReadOperations.java +++ b/nitrite/src/main/java/org/dizitart/no2/collection/operation/ReadOperations.java @@ -17,19 +17,25 @@ package org.dizitart.no2.collection.operation; import org.dizitart.no2.NitriteConfig; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.collection.*; import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.filters.*; -import org.dizitart.no2.index.IndexEntry; -import org.dizitart.no2.index.Indexer; +import org.dizitart.no2.common.streams.*; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.filters.EqualsFilter; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.filters.LogicalFilter; +import org.dizitart.no2.filters.NitriteFilter; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.NitriteIndexer; +import org.dizitart.no2.common.processors.ProcessorChain; import org.dizitart.no2.store.NitriteMap; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.List; -import static org.dizitart.no2.common.Constants.DOC_ID; +import static org.dizitart.no2.common.tuples.Pair.pair; /** * @author Anindya Chatterjee @@ -38,32 +44,32 @@ class ReadOperations { private final String collectionName; private final NitriteConfig nitriteConfig; private final NitriteMap nitriteMap; + private final FindOptimizer findOptimizer; private final IndexOperations indexOperations; + private final ProcessorChain processorChain; ReadOperations(String collectionName, + IndexOperations indexOperations, NitriteConfig nitriteConfig, NitriteMap nitriteMap, - IndexOperations indexOperations) { + ProcessorChain processorChain) { this.nitriteMap = nitriteMap; this.nitriteConfig = nitriteConfig; this.collectionName = collectionName; this.indexOperations = indexOperations; + this.findOptimizer = new FindOptimizer(); + this.processorChain = processorChain; } - public DocumentCursor find() { - RecordStream> recordStream = nitriteMap.entries(); - return new DocumentCursorImpl(recordStream); - } - - public DocumentCursor find(Filter filter) { - if (filter == null || filter == Filter.ALL) { - return find(); + public DocumentCursor find(Filter filter, FindOptions findOptions) { + if (filter == null) { + filter = Filter.ALL; } prepareFilter(filter); - - RecordStream> recordStream = findSuitableStream(filter); - return new DocumentCursorImpl(recordStream); + Collection indexDescriptors = indexOperations.listIndexes(); + FindPlan findPlan = findOptimizer.optimize(filter, findOptions, indexDescriptors); + return createCursor(findPlan); } Document getById(NitriteId nitriteId) { @@ -75,11 +81,6 @@ private void prepareFilter(Filter filter) { NitriteFilter nitriteFilter = (NitriteFilter) filter; prepareNitriteFilter(nitriteFilter); - if (filter instanceof IndexAwareFilter) { - IndexAwareFilter indexAwareFilter = (IndexAwareFilter) filter; - prepareIndexedFilter(indexAwareFilter); - } - if (filter instanceof LogicalFilter) { LogicalFilter logicalFilter = (LogicalFilter) filter; prepareLogicalFilter(logicalFilter); @@ -103,98 +104,66 @@ private void prepareLogicalFilter(LogicalFilter logicalFilter) { } } - private void prepareIndexedFilter(IndexAwareFilter indexAwareFilter) { - String field = indexAwareFilter.getField(); + private RecordStream> findSuitableStream(FindPlan findPlan) { + RecordStream> rawStream; - IndexEntry indexEntry = indexOperations.findIndexEntry(field); - if (indexEntry != null) { - String indexType = indexEntry.getIndexType(); - Indexer indexer = indexOperations.findIndexer(indexType); - if (indexer != null) { - indexAwareFilter.setIndexer(indexer); - indexAwareFilter.setIsFieldIndexed(true); + if (!findPlan.getSubPlans().isEmpty()) { + // or filters get all sub stream by finding suitable stream of all sub plans + List>> subStreams = new ArrayList<>(); + for (FindPlan subPlan : findPlan.getSubPlans()) { + RecordStream> suitableStream = findSuitableStream(subPlan); + subStreams.add(suitableStream); } - } else { - if (indexAwareFilter.getField().equals(DOC_ID)) { - // default _id index - indexAwareFilter.setOnIdField(true); - } - } - } - - private RecordStream> findSuitableStream(Filter filter) { - if (filter instanceof AndFilter) { - AndFilter andFilter = (AndFilter) filter; - Filter lhs = andFilter.getLhs(); - Filter rhs = andFilter.getRhs(); + // union of all suitable stream of all sub plans + rawStream = new UnionStream(subStreams); - if (lhs instanceof IndexAwareFilter && ((IndexAwareFilter) lhs).getIsFieldIndexed()) { - // Indexed AND Filter => IndexScan (LHS) -> Filter (RHS) - - return getFilteredStream(((IndexAwareFilter) lhs), rhs); - } else if (rhs instanceof IndexAwareFilter && ((IndexAwareFilter) rhs).getIsFieldIndexed()) { - // Non-Indexed AND Indexed => IndexScan (RHS) -> Filter (LHS) - - return getFilteredStream(((IndexAwareFilter) rhs), lhs); + // return only distinct items + rawStream = new DistinctStream(rawStream); + } else { + // and or single filter + if (findPlan.getByIdFilter() != null) { + EqualsFilter byIdFilter = findPlan.getByIdFilter(); + NitriteId nitriteId = NitriteId.createId((String) byIdFilter.getValue()); + rawStream = RecordStream.single(pair(nitriteId, nitriteMap.get(nitriteId))); } else { - // Non-Indexed AND Filter => CollectionScan - - RecordStream> recordStream = nitriteMap.entries(); - return new FilteredRecordStream(recordStream, filter); + IndexDescriptor indexDescriptor = findPlan.getIndexDescriptor(); + if (indexDescriptor != null) { + // get optimized filter + NitriteIndexer indexer = nitriteConfig.findIndexer(indexDescriptor.getIndexType()); + LinkedHashSet nitriteIds = indexer.findByFilter(findPlan, nitriteConfig); + + // create indexed stream from optimized filter + rawStream = new IndexedStream(nitriteIds, nitriteMap); + } else { + rawStream = nitriteMap.entries(); + } } - } else if (filter instanceof OrFilter) { - OrFilter orFilter = (OrFilter) filter; - Filter lhs = orFilter.getLhs(); - Filter rhs = orFilter.getRhs(); - - if (lhs instanceof IndexAwareFilter && ((IndexAwareFilter) lhs).getIsFieldIndexed() - && rhs instanceof IndexAwareFilter && ((IndexAwareFilter) rhs).getIsFieldIndexed()) { - // Indexed OR Indexed => IndexScan (LHS) Union IndexScan (RHS) - - final RecordStream> lhsStream - = getIndexedStream(((IndexAwareFilter) lhs)); - final RecordStream> rhsStream - = getIndexedStream(((IndexAwareFilter) rhs)); - - return getUnionStream(lhsStream, rhsStream); - } else { - // Non-Indexed OR Filter => CollectionScan - // Indexed OR Non-Indexed => CollectionScan - RecordStream> recordStream = nitriteMap.entries(); - return new FilteredRecordStream(recordStream, filter); + if (findPlan.getCollectionScanFilter() != null) { + rawStream = new FilteredStream(rawStream, findPlan.getCollectionScanFilter()); } - } else if (filter instanceof IndexAwareFilter && ((IndexAwareFilter) filter).getIsFieldIndexed()) { - // Indexed => IndexScan - - IndexAwareFilter indexAwareFilter = (IndexAwareFilter) filter; - return getIndexedStream(indexAwareFilter); - } else { - // Non-Indexed => CollectionScan - - RecordStream> recordStream = nitriteMap.entries(); - return new FilteredRecordStream(recordStream, filter); } - } - private RecordStream> getFilteredStream(IndexAwareFilter indexAwareFilter, - Filter rest) { - RecordStream> indexStream = getIndexedStream(indexAwareFilter); - if (rest != null) { - return new FilteredRecordStream(indexStream, rest); - } else { - return indexStream; - } - } + // sort and bound stage + if (rawStream != null) { + if (findPlan.getBlockingSortOrder() != null && !findPlan.getBlockingSortOrder().isEmpty()) { + rawStream = new SortedDocumentStream(findPlan, rawStream); + } - private RecordStream> getUnionStream( - RecordStream> lhsStream, - RecordStream> rhsStream) { + if (findPlan.getLimit() != null || findPlan.getSkip() != null) { + long limit = findPlan.getLimit() == null ? Long.MAX_VALUE : findPlan.getLimit(); + long skip = findPlan.getSkip() == null ? 0 : findPlan.getSkip(); + rawStream = new BoundedDocumentStream(skip, limit, rawStream); + } + } - return RecordStream.fromIterable(() -> new UnionStreamIterator(lhsStream, rhsStream)); + return rawStream; } - private RecordStream> getIndexedStream(IndexAwareFilter indexAwareFilter) { - return new IndexedStream(indexAwareFilter, nitriteMap); + private DocumentCursor createCursor(FindPlan findPlan) { + RecordStream> recordStream = findSuitableStream(findPlan); + DocumentStream cursor = new DocumentStream(recordStream, processorChain); + cursor.setFindPlan(findPlan); + return cursor; } } diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/operation/SortedDocumentCursor.java b/nitrite/src/main/java/org/dizitart/no2/collection/operation/SortedDocumentCursor.java deleted file mode 100644 index 3f3acf7f9..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/collection/operation/SortedDocumentCursor.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection.operation; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.common.NullOrder; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.exceptions.ValidationException; - -import java.text.Collator; -import java.util.*; - -/** - * @author Anindya Chatterjee. - */ -class SortedDocumentCursor implements RecordStream> { - private final String field; - private final SortOrder sortOrder; - private final Collator collator; - private final NullOrder nullOrder; - private final RecordStream> recordStream; - - public SortedDocumentCursor(String field, - SortOrder sortOrder, - Collator collator, - NullOrder nullOrder, - RecordStream> recordStream) { - this.field = field; - this.sortOrder = sortOrder; - this.collator = collator; - this.nullOrder = nullOrder; - this.recordStream = recordStream; - } - - @Override - public Iterator> iterator() { - Iterator> iterator = recordStream == null ? Collections.emptyIterator() - : recordStream.iterator(); - return new SortedDocumentIterator(field, sortOrder, collator, nullOrder, iterator); - } - - static class SortedDocumentIterator implements Iterator> { - private final String field; - private final SortOrder sortOrder; - private final Collator collator; - private final NullOrder nullOrder; - private final Iterator> iterator; - private Iterator> sortedIterator; - - public SortedDocumentIterator(String field, - SortOrder sortOrder, - Collator collator, - NullOrder nullOrder, - Iterator> iterator) { - this.field = field; - this.sortOrder = sortOrder; - this.collator = collator; - this.nullOrder = nullOrder; - this.iterator = iterator; - init(); - } - - @Override - public boolean hasNext() { - return sortedIterator.hasNext(); - } - - @Override - public Pair next() { - return sortedIterator.next(); - } - - private void init() { - NavigableMap>> sortedMap; - if (collator != null) { - sortedMap = new TreeMap<>(collator); - } else { - sortedMap = new TreeMap<>(); - } - - Set> nullValueEntries = new HashSet<>(); - while (iterator.hasNext()) { - Pair next = iterator.next(); - Document document = next.getSecond(); - if (document == null) continue; - - Object value = document.get(field); - if (value != null) { - if (value.getClass().isArray() || value instanceof Iterable) { - throw new ValidationException("cannot sort on an array or collection object"); - } - } else { - nullValueEntries.add(next); - continue; - } - - List> pairs; - if (sortedMap.containsKey(value)) { - pairs = sortedMap.get(value); - } else { - pairs = new ArrayList<>(); - } - pairs.add(next); - sortedMap.put(value, pairs); - } - - List> sortedPairs; - if (sortOrder == SortOrder.Ascending) { - if (nullOrder == NullOrder.Default || nullOrder == NullOrder.First) { - sortedPairs = new ArrayList<>(nullValueEntries); - sortedPairs.addAll(flattenList(sortedMap.values())); - } else { - sortedPairs = flattenList(sortedMap.values()); - sortedPairs.addAll(nullValueEntries); - } - } else { - if (nullOrder == NullOrder.Default || nullOrder == NullOrder.Last) { - sortedPairs = flattenList(sortedMap.descendingMap().values()); - sortedPairs.addAll(nullValueEntries); - } else { - sortedPairs = new ArrayList<>(nullValueEntries); - sortedPairs.addAll(flattenList(sortedMap.descendingMap().values())); - } - } - - this.sortedIterator = sortedPairs.iterator(); - } - - private List flattenList(Collection> collection) { - List finalList = new ArrayList<>(); - for (List list : collection) { - finalList.addAll(list); - } - return finalList; - } - } -} diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/operation/UnionStreamIterator.java b/nitrite/src/main/java/org/dizitart/no2/collection/operation/UnionStreamIterator.java deleted file mode 100644 index 0d3e42685..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/collection/operation/UnionStreamIterator.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2019-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection.operation; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.common.RecordStream; - -import java.util.HashSet; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.Set; - -/** - * @author Anindya Chatterjee - */ -class UnionStreamIterator implements Iterator> { - private final Iterator> lhsIterator; - private final Iterator> rhsIterator; - private final Set nitriteIds = new HashSet<>(); - private Pair nextItem; - private boolean nextItemSet = false; - - public UnionStreamIterator(RecordStream> lhsStream, - RecordStream> rhsStream) { - lhsIterator = lhsStream.iterator(); - rhsIterator = rhsStream.iterator(); - } - - @Override - public boolean hasNext() { - return nextItemSet || setNextEntry(); - } - - @Override - public Pair next() { - if (!nextItemSet && !setNextEntry()) { - throw new NoSuchElementException(); - } - nextItemSet = false; - return nextItem; - } - - private boolean setNextEntry() { - while (lhsIterator.hasNext() || rhsIterator.hasNext()) { - if (lhsIterator.hasNext()) { - Pair pair = lhsIterator.next(); - nitriteIds.add(pair.getFirst()); - nextItem = pair; - nextItemSet = true; - return true; - } - - Pair pair = rhsIterator.next(); - if (!nitriteIds.contains(pair.getFirst())) { - nextItem = pair; - nextItemSet = true; - return true; - } - } - return false; - } -} \ No newline at end of file diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/operation/WriteOperations.java b/nitrite/src/main/java/org/dizitart/no2/collection/operation/WriteOperations.java index b03b3dd01..b010409a1 100644 --- a/nitrite/src/main/java/org/dizitart/no2/collection/operation/WriteOperations.java +++ b/nitrite/src/main/java/org/dizitart/no2/collection/operation/WriteOperations.java @@ -17,17 +17,16 @@ package org.dizitart.no2.collection.operation; import lombok.extern.slf4j.Slf4j; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.collection.UpdateOptions; +import org.dizitart.no2.collection.*; import org.dizitart.no2.collection.events.CollectionEventInfo; import org.dizitart.no2.collection.events.CollectionEventListener; import org.dizitart.no2.collection.events.EventType; import org.dizitart.no2.common.WriteResult; import org.dizitart.no2.common.event.EventBus; +import org.dizitart.no2.exceptions.IndexingException; import org.dizitart.no2.exceptions.UniqueConstraintException; import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.common.processors.ProcessorChain; import org.dizitart.no2.store.NitriteMap; import java.util.HashSet; @@ -40,19 +39,22 @@ */ @Slf4j class WriteOperations { - private final IndexOperations indexOperations; + private final DocumentIndexWriter documentIndexWriter; private final ReadOperations readOperations; private final EventBus, CollectionEventListener> eventBus; private final NitriteMap nitriteMap; + private final ProcessorChain processorChain; - WriteOperations(IndexOperations indexOperations, + WriteOperations(DocumentIndexWriter documentIndexWriter, ReadOperations readOperations, NitriteMap nitriteMap, - EventBus, CollectionEventListener> eventBus) { - this.indexOperations = indexOperations; + EventBus, CollectionEventListener> eventBus, + ProcessorChain processorChain) { + this.documentIndexWriter = documentIndexWriter; this.readOperations = readOperations; this.eventBus = eventBus; this.nitriteMap = nitriteMap; + this.processorChain = processorChain; } WriteResult insert(Document... documents) { @@ -60,25 +62,30 @@ WriteResult insert(Document... documents) { log.debug("Total {} document(s) to be inserted in {}", documents.length, nitriteMap.getName()); for (Document document : documents) { - Document item = document.clone(); - NitriteId nitriteId = item.getId(); - String source = item.getSource(); + Document newDoc = document.clone(); + NitriteId nitriteId = newDoc.getId(); + String source = newDoc.getSource(); long time = System.currentTimeMillis(); - if (!REPLICATOR.contentEquals(item.getSource())) { + if (!REPLICATOR.contentEquals(newDoc.getSource())) { // if replicator is not inserting the document that means // it is being inserted by user, so update metadata - item.remove(DOC_SOURCE); - item.put(DOC_REVISION, 1); - item.put(DOC_MODIFIED, time); + newDoc.remove(DOC_SOURCE); + newDoc.put(DOC_REVISION, 1); + newDoc.put(DOC_MODIFIED, time); } else { // if replicator is inserting the document, remove the source // but keep the revision intact - item.remove(DOC_SOURCE); + newDoc.remove(DOC_SOURCE); } - log.debug("Inserting document {} in {}", item, nitriteMap.getName()); - Document already = nitriteMap.putIfAbsent(nitriteId, item); + // run processors + Document unprocessed = newDoc.clone(); + Document processed = processorChain.processBeforeWrite(unprocessed); + log.debug("Document processed from {} to {} before insert", newDoc, processed); + + log.debug("Inserting processed document {} in {}", processed, nitriteMap.getName()); + Document already = nitriteMap.putIfAbsent(nitriteId, processed); if (already != null) { log.warn("Another document {} already exists with same id {}", already, nitriteId); @@ -87,20 +94,19 @@ WriteResult insert(Document... documents) { "entry with same id already exists in " + nitriteMap.getName()); } else { try { - indexOperations.writeIndex(item, nitriteId); - } catch (UniqueConstraintException uce) { - log.error("Unique constraint violated for the document " - + document + " in " + nitriteMap.getName(), uce); + documentIndexWriter.writeIndexEntry(processed); + } catch (UniqueConstraintException | IndexingException e) { + log.error("Index operation has failed during insertion for the document " + + document + " in " + nitriteMap.getName(), e); nitriteMap.remove(nitriteId); - throw uce; + throw e; } } nitriteIds.add(nitriteId); - Document eventDoc = item.clone(); CollectionEventInfo eventInfo = new CollectionEventInfo<>(); - eventInfo.setItem(eventDoc); + eventInfo.setItem(newDoc); eventInfo.setTimestamp(time); eventInfo.setEventType(EventType.Insert); eventInfo.setOriginator(source); @@ -115,12 +121,7 @@ WriteResult insert(Document... documents) { } WriteResult update(Filter filter, Document update, UpdateOptions updateOptions) { - DocumentCursor cursor; - if (filter == null || filter == Filter.ALL) { - cursor = readOperations.find(); - } else { - cursor = readOperations.find(filter); - } + DocumentCursor cursor = readOperations.find(filter, null); WriteResultImpl writeResult = new WriteResultImpl(); Document document = update.clone(); @@ -144,38 +145,50 @@ WriteResult update(Filter filter, Document update, UpdateOptions updateOptions) break; } - Document item = doc.clone(); + Document newDoc = doc.clone(); Document oldDocument = doc.clone(); String source = document.getSource(); long time = System.currentTimeMillis(); - NitriteId nitriteId = item.getId(); - log.debug("Document to update {} in {}", item, nitriteMap.getName()); + NitriteId nitriteId = newDoc.getId(); + log.debug("Document to update {} in {}", newDoc, nitriteMap.getName()); if (!REPLICATOR.contentEquals(document.getSource())) { document.remove(DOC_SOURCE); - item.merge(document); - int rev = item.getRevision(); - item.put(DOC_REVISION, rev + 1); - item.put(DOC_MODIFIED, time); + newDoc.merge(document); + int rev = newDoc.getRevision(); + newDoc.put(DOC_REVISION, rev + 1); + newDoc.put(DOC_MODIFIED, time); } else { document.remove(DOC_SOURCE); - item.merge(document); + newDoc.merge(document); } - nitriteMap.put(nitriteId, item); - log.debug("Document {} updated in {}", item, nitriteMap.getName()); + // run processor + Document unprocessed = newDoc.clone(); + Document processed = processorChain.processBeforeWrite(unprocessed); + log.debug("Document processed from {} to {} before update", newDoc, processed); + + nitriteMap.put(nitriteId, processed); + log.debug("Document {} updated in {}", processed, nitriteMap.getName()); // if 'update' only contains id value, affected count = 0 if (document.size() > 0) { writeResult.addToList(nitriteId); } - indexOperations.updateIndex(oldDocument, item, nitriteId); + try { + documentIndexWriter.updateIndexEntry(oldDocument, processed); + } catch (UniqueConstraintException | IndexingException e) { + log.error("Index operation failed during update, reverting changes for the document " + + oldDocument + " in " + nitriteMap.getName(), e); + nitriteMap.put(nitriteId, oldDocument); + documentIndexWriter.updateIndexEntry(processed, oldDocument); + throw e; + } CollectionEventInfo eventInfo = new CollectionEventInfo<>(); - Document eventDoc = item.clone(); - eventInfo.setItem(eventDoc); + eventInfo.setItem(newDoc); eventInfo.setEventType(EventType.Update); eventInfo.setTimestamp(time); eventInfo.setOriginator(source); @@ -200,13 +213,7 @@ WriteResult update(Filter filter, Document update, UpdateOptions updateOptions) } WriteResult remove(Filter filter, boolean justOnce) { - DocumentCursor cursor; - if (filter == null || filter == Filter.ALL) { - cursor = readOperations.find(); - } else { - cursor = readOperations.find(filter); - } - + DocumentCursor cursor = readOperations.find(filter, null); WriteResultImpl result = new WriteResultImpl(); long count = 0; @@ -214,8 +221,12 @@ WriteResult remove(Filter filter, boolean justOnce) { if (document != null) { count++; - Document item = document.clone(); - CollectionEventInfo eventInfo = removeAndCreateEvent(item, result); + // run processor + Document unprocessed = document.clone(); + Document processed = processorChain.processAfterRead(unprocessed); + log.debug("Document processed from {} to {} after remove", document, processed); + + CollectionEventInfo eventInfo = removeAndCreateEvent(processed, result); if (eventInfo != null) { alert(EventType.Remove, eventInfo); } @@ -238,7 +249,7 @@ WriteResult remove(Filter filter, boolean justOnce) { return result; } - public WriteResult remove(Document document) { + WriteResult remove(Document document) { WriteResultImpl result = new WriteResultImpl(); CollectionEventInfo eventInfo = removeAndCreateEvent(document, result); if (eventInfo != null) { @@ -253,7 +264,7 @@ private CollectionEventInfo removeAndCreateEvent(Document document, Wr document = nitriteMap.remove(nitriteId); if (document != null) { long time = System.currentTimeMillis(); - indexOperations.removeIndex(document, nitriteId); + documentIndexWriter.removeIndexEntry(document); writeResult.addToList(nitriteId); int rev = document.getRevision(); diff --git a/nitrite/src/main/java/org/dizitart/no2/collection/operation/WriteResultImpl.java b/nitrite/src/main/java/org/dizitart/no2/collection/operation/WriteResultImpl.java index 4ba363118..284c8e768 100644 --- a/nitrite/src/main/java/org/dizitart/no2/collection/operation/WriteResultImpl.java +++ b/nitrite/src/main/java/org/dizitart/no2/collection/operation/WriteResultImpl.java @@ -47,8 +47,7 @@ public int getAffectedCount() { @Override public Iterator iterator() { - Iterator iterator = nitriteIds == null ? Collections.emptyIterator() + return nitriteIds == null ? Collections.emptyIterator() : nitriteIds.iterator(); - return iterator; } } diff --git a/nitrite/src/main/java/org/dizitart/no2/common/Constants.java b/nitrite/src/main/java/org/dizitart/no2/common/Constants.java index 1d5339cc5..1fe40ee42 100644 --- a/nitrite/src/main/java/org/dizitart/no2/common/Constants.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/Constants.java @@ -16,8 +16,8 @@ package org.dizitart.no2.common; -import lombok.extern.slf4j.Slf4j; import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.exceptions.NitriteIOException; import java.io.BufferedReader; import java.io.IOException; @@ -31,7 +31,6 @@ * @author Anindya Chatterjee * @since 1.0 */ -@Slf4j public class Constants { private Constants() {} @@ -42,7 +41,7 @@ private Constants() {} v = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)).readLine(); } } catch (IOException e) { - log.error("Failed to load version information", e); + throw new NitriteIOException("failed to load version information", e); } NITRITE_VERSION = v; } @@ -132,6 +131,11 @@ private Constants() {} */ public static final String TAG_KEYED_REPOSITORIES = "keyed-repositories"; + /** + * The constant TAG_COLLECTION_METADATA. + */ + public static final String TAG_MAP_METADATA = "mapNames"; + /** * The constant TAG_TYPE. */ diff --git a/nitrite/src/main/java/org/dizitart/no2/common/DBNull.java b/nitrite/src/main/java/org/dizitart/no2/common/DBNull.java new file mode 100644 index 000000000..48e8b7b37 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/DBNull.java @@ -0,0 +1,39 @@ +package org.dizitart.no2.common; + +import org.dizitart.no2.index.DBValue; + +import java.io.Serializable; + +/** + * This class acts as a surrogate for null key. + * + * @author Anindya Chatterjee + * @since 1.0 + */ +public class DBNull extends DBValue implements Serializable { + private static final long serialVersionUID = 1598819770L; + private static final DBNull instance = new DBNull(); + + private DBNull() { + super(null); + } + + @Override + public int compareTo(DBValue o) { + if (o == null || o instanceof DBNull) { + return 0; + } + + // null value always comes first + return -1; + } + + public static DBNull getInstance() { + return instance; + } + + @Override + public String toString() { + return null; + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/FieldValues.java b/nitrite/src/main/java/org/dizitart/no2/common/FieldValues.java new file mode 100644 index 000000000..56c300f98 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/FieldValues.java @@ -0,0 +1,67 @@ +package org.dizitart.no2.common; + +import lombok.Data; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.common.util.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a {@link Fields} and their corresponding values from a document. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +@Data +public class FieldValues { + private NitriteId nitriteId; + private Fields fields; + private List> values; + + /** + * Instantiates a new Field values. + */ + public FieldValues() { + values = new ArrayList<>(); + } + + /** + * Get the value of the field. + * + * @param field the field + * @return the value + */ + public Object get(String field) { + if (fields.getFieldNames().contains(field)) { + for (Pair value : values) { + if (value.getFirst().equals(field)) { + return value.getSecond(); + } + } + } + return null; + } + + /** + * Gets the {@link Fields}. + * + * @return the fields + */ + public Fields getFields() { + if (fields != null) { + return fields; + } + + this.fields = new Fields(); + List fieldNames = new ArrayList<>(); + for (Pair value : getValues()) { + if (!StringUtils.isNullOrEmpty(value.getFirst())) { + fieldNames.add(value.getFirst()); + } + } + fields.setFieldNames(fieldNames); + return fields; + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/Fields.java b/nitrite/src/main/java/org/dizitart/no2/common/Fields.java new file mode 100644 index 000000000..e5f380868 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/Fields.java @@ -0,0 +1,147 @@ +package org.dizitart.no2.common; + +import lombok.AccessLevel; +import lombok.EqualsAndHashCode; +import lombok.Setter; +import org.dizitart.no2.common.util.StringUtils; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.dizitart.no2.common.Constants.INTERNAL_NAME_SEPARATOR; +import static org.dizitart.no2.common.util.ValidationUtils.notEmpty; +import static org.dizitart.no2.common.util.ValidationUtils.notNull; + +/** + * Represents a list of document fields. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +@EqualsAndHashCode +public class Fields implements Comparable, Serializable { + private static final long serialVersionUID = 1601646404L; + + /** + * The Field names. + */ + @Setter(AccessLevel.PACKAGE) + protected List fieldNames; + + /** + * Instantiates a new Fields. + */ + public Fields() { + fieldNames = new ArrayList<>(); + } + + /** + * Creates a {@link Fields} instance with field names. + * + * @param fields the fields + * @return the fields + */ + public static Fields withNames(String... fields) { + notNull(fields, "fields cannot be null"); + notEmpty(fields, "fields cannot be empty"); + + Fields f = new Fields(); + f.fieldNames.addAll(Arrays.asList(fields)); + return f; + } + + + /** + * Adds a new field name. + * + * @param field the field + * @return the fields + */ + public Fields addField(String field) { + fieldNames.add(field); + return this; + } + + /** + * Gets the field names. + * + * @return the field names + */ + public List getFieldNames() { + return Collections.unmodifiableList(fieldNames); + } + + /** + * Starts with boolean. + * + * @param other the other + * @return the boolean + */ + public boolean startsWith(Fields other) { + if (other != null) { + int length = Math.min(fieldNames.size(), other.fieldNames.size()); + + // if other is greater then it is not a prefix of this field + if (other.fieldNames.size() > length) return false; + + for (int i = 0; i < length; i++) { + String thisField = fieldNames.get(i); + String otherField = other.fieldNames.get(i); + if (!thisField.equals(otherField)) { + return false; + } + } + return true; + } + return false; + } + + /** + * Gets the encoded name for this {@link Fields}. + * + * @return the encoded name + */ + public String getEncodedName() { + return StringUtils.join(INTERNAL_NAME_SEPARATOR, getFieldNames()); + } + + @Override + public String toString() { + return fieldNames.toString(); + } + + @Override + public int compareTo(Fields other) { + if (other == null) return 1; + int fieldsSize = getFieldNames().size(); + int otherFieldsSize = other.getFieldNames().size(); + int result = Integer.compare(fieldsSize, otherFieldsSize); + if (result == 0) { + String[] keys = getFieldNames().toArray(new String[0]); + String[] otherKeys = other.getFieldNames().toArray(new String[0]); + for (int i = 0; i < keys.length; i++) { + int cmp = keys[i].compareTo(otherKeys[i]); + if (cmp != 0) { + return cmp; + } + } + } + + return result; + } + + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.writeObject(fieldNames); + } + + @SuppressWarnings("unchecked") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + fieldNames = (List) stream.readObject(); + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/NullEntry.java b/nitrite/src/main/java/org/dizitart/no2/common/NullEntry.java deleted file mode 100644 index ac56c9079..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/common/NullEntry.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.dizitart.no2.common; - -import java.io.Serializable; - -/** - * This class acts as a surrogate for null key. - * - * @author Anindya Chatterjee - */ -public class NullEntry implements Comparable, Serializable { - private static final long serialVersionUID = 1598819770L; - private static final NullEntry instance = new NullEntry(); - - private NullEntry() { - } - - @Override - public int compareTo(NullEntry o) { - return 0; - } - - public static NullEntry getInstance() { - return instance; - } -} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/NullOrder.java b/nitrite/src/main/java/org/dizitart/no2/common/NullOrder.java deleted file mode 100644 index 4d913964f..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/common/NullOrder.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.common; - -/** - * An enum to specify where to place `null` values during sort. - * - * @author Anindya Chatterjee - * @since 3.1.0 - */ -public enum NullOrder { - /** - * Places `null` values at first. - */ - First, - - /** - * Places `null` values at last. - */ - Last, - - /** - * Places `null` values at default location. - */ - Default -} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/PersistentCollection.java b/nitrite/src/main/java/org/dizitart/no2/common/PersistentCollection.java index 205d4d52b..395dedc9a 100644 --- a/nitrite/src/main/java/org/dizitart/no2/common/PersistentCollection.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/PersistentCollection.java @@ -22,13 +22,13 @@ import org.dizitart.no2.collection.events.EventAware; import org.dizitart.no2.collection.events.EventType; import org.dizitart.no2.collection.meta.MetadataAware; -import org.dizitart.no2.index.IndexEntry; +import org.dizitart.no2.index.IndexDescriptor; import org.dizitart.no2.index.IndexOptions; import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.processors.Processor; import org.dizitart.no2.repository.ObjectRepository; import org.dizitart.no2.store.NitriteStore; -import java.io.Closeable; import java.util.Collection; /** @@ -40,75 +40,100 @@ * @see ObjectRepository * @since 1.0 */ -public interface PersistentCollection extends EventAware, MetadataAware, Closeable { +public interface PersistentCollection extends EventAware, MetadataAware, AutoCloseable { + + /** + * Adds a data processor to this collection. + * + * @param processor the processor + */ + void addProcessor(Processor processor); + /** - * Creates an index on `value`, if not already exists. - * If `indexOptions` is `null`, it will use default options. + * Removes a data processor from this collection. + * + * @param processor the processor + */ + void removeProcessor(Processor processor); + + /** + * Creates an unique index on the {@code fields}, if not already exists. + * + * @param fields the fields to be indexed. + * @throws org.dizitart.no2.exceptions.IndexingException if an index already exists on the field. + */ + default void createIndex(String... fields) { + createIndex(null, fields); + } + + /** + * Creates an index on the {@code fields}, if not already exists. + * If {@code indexOptions} is {@code null}, it will use default options. *

    - * The default indexing option is - *

    - * - `indexOptions.setAsync(false);` - * - `indexOptions.setIndexType(IndexType.Unique);` + * The default indexing option is - + * + *

      + *
    • {@code indexOptions.setIndexType(IndexType.Unique);}
    • + *
    + * *

    - * [icon="{@docRoot}/note.png"] - * [NOTE] - * ==== - * - '_id' value of the document is always indexed. But full text - * indexing is not supported on '_id' value. - * - Compound index is not supported. - * - Indexing on arrays or collection is not supported - * - Indexing on non-comparable value is not supported - * ==== - * - * @param field the value to be indexed. + * NOTE: + *

      + *
    • _id value of the document is always indexed. But full-text indexing is not supported on _id value.
    • + *
    • Indexing on non-comparable value is not supported.
    • + *
    + *

    + * * @param indexOptions index options. - * @throws org.dizitart.no2.exceptions.IndexingException if an index already exists on `value`. + * @param fields the fields to be indexed. + * @throws org.dizitart.no2.exceptions.IndexingException if an index already exists on the field. * @see org.dizitart.no2.index.IndexOptions * @see IndexType */ - void createIndex(String field, IndexOptions indexOptions); + void createIndex(IndexOptions indexOptions, String... fields); /** - * Rebuilds index on `field` if it exists. + * Rebuilds index on the {@code field} if it exists. * - * @param field the value to be indexed. - * @param isAsync if set to `true`, the indexing will run in background; otherwise, in foreground. - * @throws org.dizitart.no2.exceptions.IndexingException if the `field` is not indexed. + * @param fields the fields to be indexed. + * @throws org.dizitart.no2.exceptions.IndexingException if the {@code field} is not indexed. */ - void rebuildIndex(String field, boolean isAsync); + void rebuildIndex(String... fields); + /** * Gets a set of all indices in the collection. * * @return a set of all indices. - * @see IndexEntry + * @see IndexDescriptor */ - Collection listIndices(); + Collection listIndices(); /** - * Checks if a value is already indexed or not. + * Checks if the {@code fields} is already indexed or not. * - * @param field the value to check. - * @return `true` if the `value` is indexed; otherwise, `false`. + * @param fields the fields to check. + * @return {@code true} if the {@code field} is indexed; otherwise, {@code false}. */ - boolean hasIndex(String field); + boolean hasIndex(String... fields); /** - * Checks if indexing operation is currently ongoing for a `field`. + * Checks if indexing operation is currently ongoing for the {@code fields}. * - * @param field the value to check. - * @return `true` if indexing is currently running; otherwise, `false`. + * @param fields the fields to check. + * @return {@code true} if indexing is currently running; otherwise, {@code false}. */ - boolean isIndexing(String field); + boolean isIndexing(String... fields); /** - * Drops the index on a `field`. + * Drops the index on the {@code fields}. * - * @param field the index of the `field` to drop. - * @throws org.dizitart.no2.exceptions.IndexingException if indexing is currently running on the `field`. - * @throws org.dizitart.no2.exceptions.IndexingException if the `field` is not indexed. + * @param fields the index on the {@code fields} to drop. + * @throws org.dizitart.no2.exceptions.IndexingException if indexing is currently running on the {@code fields}. + * @throws org.dizitart.no2.exceptions.IndexingException if the {@code fields} are not indexed. */ - void dropIndex(String field); + void dropIndex(String... fields); /** * Drops all indices from the collection. @@ -118,27 +143,27 @@ public interface PersistentCollection extends EventAware, MetadataAware, Clos void dropAllIndices(); /** - * Inserts elements into this collection. If the element has an '_id' field, + * Inserts elements into this collection. If the element has an _id field, * then the value will be used as an unique key to identify the element - * in the collection. If the element does not have any '_id' field, - * then nitrite will generate a new {@link org.dizitart.no2.collection.NitriteId} and will add it to the '_id' + * in the collection. If the element does not have any _id field, + * then nitrite will generate a new {@link org.dizitart.no2.collection.NitriteId} and will add it to the _id * field. *

    * If any of the value is already indexed in the collection, then after insertion the * index will also be updated. *

    - * [icon="{@docRoot}/note.png"] + *

    * NOTE: This operations will notify all {@link CollectionEventListener} - * instances registered to this collection with change type - * {@link EventType#Insert}. + * instances registered to this collection with change type {@link EventType#Insert}. + *

    * * @param elements an array of element for batch insertion. * @return the result of the write operation. - * @throws org.dizitart.no2.exceptions.ValidationException if `elements` is `null`. - * @throws org.dizitart.no2.exceptions.InvalidIdException if the '_id' field's value contains `null`. - * @throws org.dizitart.no2.exceptions.InvalidIdException if the '_id' field's value contains non comparable type, i.e. type that does not implement {@link Comparable}. - * @throws org.dizitart.no2.exceptions.InvalidIdException if the '_id' field contains value which is not of the same java type as of other element's '_id' field value in the collection. - * @throws org.dizitart.no2.exceptions.UniqueConstraintException if the value of '_id' field clashes with the '_id' field of another element in the repository. + * @throws org.dizitart.no2.exceptions.ValidationException if elements is null. + * @throws org.dizitart.no2.exceptions.InvalidIdException if the _id field's value contains {@code null}. + * @throws org.dizitart.no2.exceptions.InvalidIdException if the _id field's value contains non comparable type, i.e. type that does not implement {@link Comparable}. + * @throws org.dizitart.no2.exceptions.InvalidIdException if the _id field contains value which is not of the same java type as of other element's _id field value in the collection. + * @throws org.dizitart.no2.exceptions.UniqueConstraintException if the value of _id field clashes with the _id field of another element in the repository. * @throws org.dizitart.no2.exceptions.UniqueConstraintException if a value of the element is indexed and it violates the unique constraint in the collection(if any). * @see NitriteId * @see WriteResult @@ -146,61 +171,59 @@ public interface PersistentCollection extends EventAware, MetadataAware, Clos WriteResult insert(T[] elements); /** - * Updates `element` in the collection. Specified `element` must have an id. + * Updates the {@code element} in the collection. Specified {@code element} must have an id. *

    - * [icon="{@docRoot}/note.png"] * NOTE: This operations will notify all {@link CollectionEventListener} * instances registered to this collection with change type * {@link EventType#Update}. + *

    * * @param element the element to update. * @return the result of the update operation. - * @throws org.dizitart.no2.exceptions.ValidationException if the `element` is `null`. - * @throws org.dizitart.no2.exceptions.NotIdentifiableException if the `element` does not have any id. + * @throws org.dizitart.no2.exceptions.ValidationException if the element is {@code null}. + * @throws org.dizitart.no2.exceptions.NotIdentifiableException if the element does not have any id. */ default WriteResult update(T element) { return update(element, false); } /** - * Updates `element` in the collection. Specified `element` must have an id. - * If the `element` is not found in the collection, it will be inserted only if `upsert` - * is set to `true`. + * Updates {@code element} in the collection. Specified {@code element} must have an id. + * If the {@code element} is not found in the collection, it will be inserted only if {@code insertIfAbsent} + * is set to {@code true}. + *

    *

    - * [icon="{@docRoot}/note.png"] * NOTE: This operations will notify all {@link CollectionEventListener} * instances registered to this collection with change type - * {@link EventType#Update} - * or {@link EventType#Insert}. + * {@link EventType#Update} or {@link EventType#Insert}. + *

    * * @param element the element to update. - * @param insertIfAbsent if set to `true`, `element` will be inserted if not found. + * @param insertIfAbsent if set to {@code true}, {@code element} will be inserted if not found. * @return the result of the update operation. - * @throws org.dizitart.no2.exceptions.ValidationException if the `element` is `null`. - * @throws org.dizitart.no2.exceptions.NotIdentifiableException if the `element` - * does not have any id field. + * @throws org.dizitart.no2.exceptions.ValidationException if the {@code element} is {@code null}. + * @throws org.dizitart.no2.exceptions.NotIdentifiableException if the {@code element} does not have any id field. */ WriteResult update(T element, boolean insertIfAbsent); /** - * Deletes the `element` from the collection. The `element` must have an id. + * Deletes the {@code element} from the collection. The {@code element} must have an id. + * *

    - * [icon="{@docRoot}/note.png"] * NOTE: This operations will notify all {@link CollectionEventListener} * instances registered to this collection with change type * {@link EventType#Remove}. + *

    * * @param element the element * @return the result of the remove operation. - * @throws org.dizitart.no2.exceptions.NotIdentifiableException if the `element` does not - * have any id field. + * @throws org.dizitart.no2.exceptions.NotIdentifiableException if the {@code element} does not have any id field. */ WriteResult remove(T element); /** * Removes all element from the collection. - * - * */ + */ void clear(); /** @@ -213,28 +236,19 @@ default WriteResult update(T element) { void drop(); /** - * Returns `true` if the collection is dropped; otherwise, `false`. + * Returns {@code true} if the collection is dropped; otherwise, {@code false}. * * @return a boolean value indicating if the collection has been dropped or not. */ boolean isDropped(); /** - * Returns `true` if the collection is open; otherwise, `false`. + * Returns {@code true} if the collection is open; otherwise, {@code false}. * * @return a boolean value indicating if the collection has been closed or not. */ boolean isOpen(); - /** - * Closes the collection for further access. If a collection once closed - * can only be opened via {@link org.dizitart.no2.Nitrite#getCollection(String)} or - * {@link org.dizitart.no2.Nitrite#getRepository(Class)} operation. - *

    - * Any access to a closed collection would result into a {@link IllegalStateException}. - */ - void close(); - /** * Returns the size of the {@link PersistentCollection}. * @@ -242,6 +256,11 @@ default WriteResult update(T element) { */ long size(); + /** + * Closes this {@link PersistentCollection}. + * */ + void close(); + /** * Returns the {@link NitriteStore} instance for this collection. * diff --git a/nitrite/src/main/java/org/dizitart/no2/common/RecordStream.java b/nitrite/src/main/java/org/dizitart/no2/common/RecordStream.java index cf88a21e5..2bfc34ea6 100644 --- a/nitrite/src/main/java/org/dizitart/no2/common/RecordStream.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/RecordStream.java @@ -21,13 +21,32 @@ import java.util.*; /** + * Represents a record stream which can be iterated in a for loop. + * + * @param the type parameter * @author Anindya Chatterjee. + * @since 1.0 */ public interface RecordStream extends Iterable { + /** + * Creates a {@link RecordStream} from an {@link Iterable}. + * + * @param the type parameter + * @param iterable the iterable + * @return the record stream + */ static RecordStream fromIterable(Iterable iterable) { return iterable::iterator; } + /** + * Creates a {@link RecordStream} by combining two {@link Iterable}s. + * + * @param the type parameter + * @param first the first + * @param second the second + * @return the record stream + */ static RecordStream fromCombined(Iterable first, Iterable second) { return RecordStream.fromIterable(() -> new Iterator() { private final Iterator firstIterator = first != null ? first.iterator() : Collections.emptyIterator(); @@ -53,6 +72,14 @@ public T next() { }); } + /** + * Creates a {@link RecordStream} by eliminating elements from an {@link Iterable}. + * + * @param the type parameter + * @param iterable the iterable + * @param elements the elements + * @return the record stream + */ static RecordStream except(Iterable iterable, Collection elements) { return RecordStream.fromIterable(() -> new Iterator() { private final Iterator iterator = iterable != null ? iterable.iterator() : Collections.emptyIterator(); @@ -87,31 +114,67 @@ private boolean setNextId() { }); } + /** + * Creates an empty {@link RecordStream}. + * + * @param the type parameter + * @return the record stream + */ static RecordStream empty() { return RecordStream.fromIterable(Collections.emptySet()); } + /** + * Creates a {@link RecordStream} with a single element. + * + * @param the type parameter + * @param v the v + * @return the record stream + */ + static RecordStream single(V v) { + return RecordStream.fromIterable(Collections.singleton(v)); + } + + /** + * Gets the size of the {@link RecordStream}. + * + * @return the long + */ default long size() { return Iterables.size(this); } + /** + * Creates a {@link List} from a {@link RecordStream} by iterating it. + * + * @return the list + */ default List toList() { - return Iterables.toList(this); + return Collections.unmodifiableList(Iterables.toList(this)); } + /** + * Creates a {@link Set} from a {@link RecordStream} by iterating it. + * + * @return the set + */ default Set toSet() { - return Iterables.toSet(this); + return Collections.unmodifiableSet(Iterables.toSet(this)); } + /** + * Checks if this {@link RecordStream} has any elements or not. + * + * @return the boolean + */ default boolean isEmpty() { return !iterator().hasNext(); } /** - * Gets the first element of the result or - * `null` if it is empty. + * Gets the first element of the result or null if it is empty. * - * @return the first element or `null` + * @return the first element or null */ default T firstOrNull() { return Iterables.firstOrNull(this); diff --git a/nitrite/src/main/java/org/dizitart/no2/common/SortableFields.java b/nitrite/src/main/java/org/dizitart/no2/common/SortableFields.java new file mode 100644 index 000000000..7b2b67642 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/SortableFields.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common; + +import lombok.AccessLevel; +import lombok.Setter; +import org.dizitart.no2.common.tuples.Pair; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static org.dizitart.no2.common.util.ValidationUtils.notEmpty; +import static org.dizitart.no2.common.util.ValidationUtils.notNull; + +/** + * Represents a list of document field with + * sorting direction for find query. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +public class SortableFields extends Fields { + @Setter(AccessLevel.PACKAGE) + private List> sortingOrders; + + /** + * Instantiates a new {@link SortableFields}. + */ + public SortableFields() { + super(); + sortingOrders = new ArrayList<>(); + } + + /** + * Creates a {@link SortableFields} instance with field names. + * + * @param fields the fields + * @return the fields + */ + public static SortableFields withNames(String... fields) { + notNull(fields, "fields cannot be null"); + notEmpty(fields, "fields cannot be empty"); + + SortableFields sortableFields = new SortableFields(); + for (String field : fields) { + sortableFields.addField(field, SortOrder.Ascending); + } + return sortableFields; + } + + /** + * Adds the sort order for a field. + * + * @param field the field + * @param sortOrder the sort order + * @return the sortable fields + */ + public SortableFields addField(String field, SortOrder sortOrder) { + super.fieldNames.add(field); + this.sortingOrders.add(Pair.pair(field, sortOrder)); + return this; + } + + /** + * Gets the sort by field specifications. + * + * @return the sort specs + */ + public List> getSortingOrders() { + return Collections.unmodifiableList(sortingOrders); + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/UnknownType.java b/nitrite/src/main/java/org/dizitart/no2/common/UnknownType.java index b048f96e8..db54acd0b 100644 --- a/nitrite/src/main/java/org/dizitart/no2/common/UnknownType.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/UnknownType.java @@ -1,7 +1,10 @@ package org.dizitart.no2.common; /** + * Represents an unknown type. + * * @author Anindya Chatterjee + * @since 4.0 */ public class UnknownType implements Comparable { @Override diff --git a/nitrite/src/main/java/org/dizitart/no2/common/concurrent/LockService.java b/nitrite/src/main/java/org/dizitart/no2/common/concurrent/LockService.java index 3ddda4235..37c20625a 100644 --- a/nitrite/src/main/java/org/dizitart/no2/common/concurrent/LockService.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/concurrent/LockService.java @@ -6,15 +6,27 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; /** + * The lock service. + * * @author Anindya Chatterjee + * @since 4.0 */ public class LockService { private final Map lockRegistry; + /** + * Instantiates a new Lock service. + */ public LockService() { this.lockRegistry = new HashMap<>(); } + /** + * Gets read lock. + * + * @param name the name + * @return the read lock + */ public synchronized Lock getReadLock(String name) { if (lockRegistry.containsKey(name)) { ReentrantReadWriteLock rwLock = lockRegistry.get(name); @@ -25,6 +37,12 @@ public synchronized Lock getReadLock(String name) { return rwLock.readLock(); } + /** + * Gets write lock. + * + * @param name the name + * @return the write lock + */ public synchronized Lock getWriteLock(String name) { if (lockRegistry.containsKey(name)) { ReentrantReadWriteLock rwLock = lockRegistry.get(name); diff --git a/nitrite/src/main/java/org/dizitart/no2/common/concurrent/ThreadPoolManager.java b/nitrite/src/main/java/org/dizitart/no2/common/concurrent/ThreadPoolManager.java index a3921546b..a3f84158b 100644 --- a/nitrite/src/main/java/org/dizitart/no2/common/concurrent/ThreadPoolManager.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/concurrent/ThreadPoolManager.java @@ -22,6 +22,7 @@ import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import static org.dizitart.no2.common.Constants.DAEMON_THREAD_NAME; @@ -30,7 +31,7 @@ * A factory class for creating {@link ExecutorService}. * * @author Anindya Chatterjee. - * @since 4.0.0 + * @since 4.0 */ @Slf4j public class ThreadPoolManager { @@ -69,6 +70,13 @@ public static ExecutorService getThreadPool(int size, String threadName) { return threadPool; } + /** + * Returns a new {@link ErrorAwareThreadFactory} where thread name + * will be set to the name specified. + * + * @param name the name + * @return the error aware thread factory + */ public static ErrorAwareThreadFactory threadFactory(String name) { return new ErrorAwareThreadFactory() { @Override @@ -81,10 +89,19 @@ public Thread createThread(Runnable runnable) { }; } - public static void runAsync(Runnable runnable) { - commonPool.submit(runnable); + /** + * Submits a runnable task asynchronously on common pool. + * + * @param runnable the runnable task + * @return the future + */ + public static Future runAsync(Runnable runnable) { + return commonPool.submit(runnable); } + /** + * Shuts down all thread pools. + */ public static void shutdownThreadPools() { for (ExecutorService threadPool : threadPools) { synchronized (lock) { diff --git a/nitrite/src/main/java/org/dizitart/no2/common/crypto/AESEncryptor.java b/nitrite/src/main/java/org/dizitart/no2/common/crypto/AESEncryptor.java new file mode 100644 index 000000000..467a2ab16 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/crypto/AESEncryptor.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.crypto; + +import org.dizitart.no2.common.util.Base64; +import org.dizitart.no2.common.util.CryptoUtils; +import org.dizitart.no2.common.util.SecureString; +import org.dizitart.no2.exceptions.NitriteSecurityException; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.GCMParameterSpec; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +/** + * A password based AES string encryption utility. + * + *

    + * NOTE: This is a derivative work of https://mkyong.com/java/java-symmetric-key-cryptography-example/ + *

    + * + * @author Anindya Chatterjee + * @since 4.0 + */ +public class AESEncryptor implements Encryptor { + private final String encryptAlgo; + private final int tagLengthBit; + private final int ivLengthByte; + private final int saltLengthByte; + private final Charset UTF_8 = StandardCharsets.UTF_8; + + private final SecureString password; + + /** + * Instantiates a new {@link AESEncryptor} with these default values + *

    + *

      + *
    • Encryption Algo - AES/GCM/NoPadding
    • + *
    • Tag Length (bit) - 128
    • + *
    • IV Length (byte) - 12
    • + *
    • Salt Length (byte) - 16
    • + *
    + *

    + * + * @param password the password + */ + public AESEncryptor(String password) { + this(password, "AES/GCM/NoPadding", 128, 12, 16); + } + + /** + * Instantiates a new {@link AESEncryptor}. + * + * @param password the password + * @param encryptionAlgo the encryption algo + * @param tagLengthBit the tag length bit + * @param ivLengthByte the iv length byte + * @param saltLengthByte the salt length byte + */ + public AESEncryptor(String password, String encryptionAlgo, + Integer tagLengthBit, Integer ivLengthByte, + Integer saltLengthByte) { + this.password = new SecureString(password); + this.encryptAlgo = encryptionAlgo; + this.tagLengthBit = tagLengthBit; + this.ivLengthByte = ivLengthByte; + this.saltLengthByte = saltLengthByte; + } + + /** + * Returns a base64 encoded AES encrypted string. + * + * @param plainText the text as byte array + * @return the encrypted string + */ + @Override + public String encrypt(byte[] plainText) { + try { + // 16 bytes salt + byte[] salt = CryptoUtils.getRandomNonce(saltLengthByte); + + // GCM recommended 12 bytes iv? + byte[] iv = CryptoUtils.getRandomNonce(ivLengthByte); + + // secret key from password + SecretKey aesKeyFromPassword = CryptoUtils.getAESKeyFromPassword(password.asString().toCharArray(), salt); + + Cipher cipher = Cipher.getInstance(encryptAlgo); + + // ASE-GCM needs GCMParameterSpec + cipher.init(Cipher.ENCRYPT_MODE, aesKeyFromPassword, new GCMParameterSpec(tagLengthBit, iv)); + + byte[] cipherText = cipher.doFinal(plainText); + + // prefix IV and Salt to cipher text + byte[] cipherTextWithIvSalt = ByteBuffer.allocate(iv.length + salt.length + cipherText.length) + .put(iv) + .put(salt) + .put(cipherText) + .array(); + + // string representation, base64, send this string to other for decryption. + return Base64.encodeToString(cipherTextWithIvSalt, Base64.URL_SAFE); + } catch (Exception e) { + throw new NitriteSecurityException("failed to encrypt data", e); + } + } + + /** + * Returns the decrypted string encoded by AES. + * + *

    + * NOTE: The same password, salt and iv are needed to decrypt it. + *

    + * @param encryptedText the encrypted text + * @return the plain text decrypted string + */ + @Override + public String decrypt(String encryptedText) { + try { + byte[] decode = Base64.decode(encryptedText.getBytes(UTF_8), Base64.URL_SAFE); + + // get back the iv and salt from the cipher text + ByteBuffer bb = ByteBuffer.wrap(decode); + byte[] iv = new byte[ivLengthByte]; + bb.get(iv); + + byte[] salt = new byte[saltLengthByte]; + bb.get(salt); + + byte[] cipherText = new byte[bb.remaining()]; + bb.get(cipherText); + + // get back the aes key from the same password and salt + SecretKey aesKeyFromPassword = CryptoUtils.getAESKeyFromPassword(password.asString().toCharArray(), salt); + Cipher cipher = Cipher.getInstance(encryptAlgo); + cipher.init(Cipher.DECRYPT_MODE, aesKeyFromPassword, new GCMParameterSpec(tagLengthBit, iv)); + byte[] plainText = cipher.doFinal(cipherText); + return new String(plainText, UTF_8); + } catch (Exception e) { + throw new NitriteSecurityException("failed to decrypt data", e); + } + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/crypto/Encryptor.java b/nitrite/src/main/java/org/dizitart/no2/common/crypto/Encryptor.java new file mode 100644 index 000000000..4d32637f5 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/crypto/Encryptor.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.crypto; + +/** + * Represents a symmetric key string encryptor. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +public interface Encryptor { + /** + * Returns a base64 encoded encrypted string. + * + * @param plainText the plain text + * @return the encrypted string + */ + String encrypt(byte[] plainText); + + /** + * Returns the decrypted string, encoded by this encryptor. + * + * @param encryptedText the encrypted text + * @return the string + */ + String decrypt(String encryptedText); +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/event/EventBus.java b/nitrite/src/main/java/org/dizitart/no2/common/event/EventBus.java index f73f208be..e9bc7538b 100644 --- a/nitrite/src/main/java/org/dizitart/no2/common/event/EventBus.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/event/EventBus.java @@ -51,7 +51,7 @@ public interface EventBus extends AutoCloseable { void post(EventInfo eventInfo); /** - * Closes the event bus and de-registers all event listeners. - */ + * Closes this {@link EventBus} instance. + * */ void close(); } diff --git a/nitrite/src/main/java/org/dizitart/no2/mapper/Mappable.java b/nitrite/src/main/java/org/dizitart/no2/common/mapper/Mappable.java similarity index 97% rename from nitrite/src/main/java/org/dizitart/no2/mapper/Mappable.java rename to nitrite/src/main/java/org/dizitart/no2/common/mapper/Mappable.java index b4c5a9ab8..d16297757 100644 --- a/nitrite/src/main/java/org/dizitart/no2/mapper/Mappable.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/mapper/Mappable.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.dizitart.no2.mapper; +package org.dizitart.no2.common.mapper; import org.dizitart.no2.collection.Document; diff --git a/nitrite/src/main/java/org/dizitart/no2/mapper/MappableMapper.java b/nitrite/src/main/java/org/dizitart/no2/common/mapper/MappableMapper.java similarity index 82% rename from nitrite/src/main/java/org/dizitart/no2/mapper/MappableMapper.java rename to nitrite/src/main/java/org/dizitart/no2/common/mapper/MappableMapper.java index e196bae5a..443fb4666 100644 --- a/nitrite/src/main/java/org/dizitart/no2/mapper/MappableMapper.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/mapper/MappableMapper.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.dizitart.no2.mapper; +package org.dizitart.no2.common.mapper; import org.dizitart.no2.NitriteConfig; import org.dizitart.no2.collection.Document; @@ -27,36 +27,32 @@ import static org.dizitart.no2.common.util.ObjectUtils.newInstance; /** + * A {@link NitriteMapper} based on {@link Mappable} implementation. + * * @author Anindya Chatterjee. + * @since 4.0 */ public class MappableMapper implements NitriteMapper { private final Set> valueTypes; + /** + * Instantiates a new {@link MappableMapper}. + * + * @param valueTypes the value types + */ public MappableMapper(Class... valueTypes) { this.valueTypes = new HashSet<>(); init(listOf(valueTypes)); } - @Override - @SuppressWarnings("unchecked") - public Target convert(Source source, Class type) { - if (source == null) { - return null; - } - - if (isValue(source)) { - return (Target) source; - } else { - if (Document.class.isAssignableFrom(type)) { - return (Target) convertToDocument(source); - } else if (source instanceof Document) { - return convertFromDocument((Document) source, type); - } - } - - throw new ObjectMappingException("object must implements Mappable"); - } - + /** + * Converts a document to a target object of type Target. + * + * @param the type parameter + * @param source the source + * @param type the type + * @return the target + */ protected Target convertFromDocument(Document source, Class type) { if (source == null) { return null; @@ -73,6 +69,13 @@ protected Target convertFromDocument(Document source, Class typ throw new ObjectMappingException("object must implements Mappable"); } + /** + * Converts an object of type Source to a document. + * + * @param the type parameter + * @param source the source + * @return the document + */ protected Document convertToDocument(Source source) { if (source instanceof Mappable) { Mappable mappable = (Mappable) source; @@ -82,6 +85,35 @@ protected Document convertToDocument(Source source) { throw new ObjectMappingException("object must implements Mappable"); } + /** + * Adds a value type to ignore during mapping. + * + * @param valueType the value type + */ + protected void addValueType(Class valueType) { + this.valueTypes.add(valueType); + } + + @Override + @SuppressWarnings("unchecked") + public Target convert(Source source, Class type) { + if (source == null) { + return null; + } + + if (isValue(source)) { + return (Target) source; + } else { + if (Document.class.isAssignableFrom(type)) { + return (Target) convertToDocument(source); + } else if (source instanceof Document) { + return convertFromDocument((Document) source, type); + } + } + + throw new ObjectMappingException("object must implements Mappable"); + } + @Override public boolean isValueType(Class type) { if (type.isPrimitive() && type != void.class) return true; @@ -102,10 +134,6 @@ public void initialize(NitriteConfig nitriteConfig) { } - protected void addValueType(Class valueType) { - this.valueTypes.add(valueType); - } - private void init(List> valueTypes) { this.valueTypes.add(Number.class); this.valueTypes.add(Boolean.class); diff --git a/nitrite/src/main/java/org/dizitart/no2/common/mapper/NitriteMapper.java b/nitrite/src/main/java/org/dizitart/no2/common/mapper/NitriteMapper.java new file mode 100644 index 000000000..1f6e606ce --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/mapper/NitriteMapper.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017-2020. Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.mapper; + +import org.dizitart.no2.common.module.NitritePlugin; + +/** + * Represents a mapper which will convert a object of one type to an object of another type. + * + * @author Anindya Chatterjee. + * @since 4.0 + */ +public interface NitriteMapper extends NitritePlugin { + /** + * Converts an object of type Source to an object of type Target. + * + * @param the type parameter + * @param the type parameter + * @param source the source + * @param type the type + * @return the target + */ + Target convert(Source source, Class type); + + /** + * Checks if the provided type is registered as a value type. + * + * @param type the type + * @return the boolean + */ + boolean isValueType(Class type); + + /** + * Checks if an object is of a value type. + * + * @param object the object + * @return the boolean + */ + boolean isValue(Object object); +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/module/NitriteModule.java b/nitrite/src/main/java/org/dizitart/no2/common/module/NitriteModule.java new file mode 100644 index 000000000..4404d5ac7 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/module/NitriteModule.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017-2020. Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.module; + +import java.util.Set; + +import static org.dizitart.no2.common.util.Iterables.setOf; + +/** + * Represents a nitrite plugin modules which may contains + * one or more nitrite plugins. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +public interface NitriteModule { + /** + * Creates a {@link NitriteModule} from a set of {@link NitritePlugin}s. + * + * @param plugins the plugins + * @return the nitrite module + */ + static NitriteModule module(NitritePlugin... plugins) { + return () -> setOf(plugins); + } + + /** + * Returns the set of {@link NitritePlugin} encapsulated by this module. + * + * @return the set + */ + Set plugins(); +} diff --git a/nitrite/src/main/java/org/dizitart/no2/module/NitritePlugin.java b/nitrite/src/main/java/org/dizitart/no2/common/module/NitritePlugin.java similarity index 78% rename from nitrite/src/main/java/org/dizitart/no2/module/NitritePlugin.java rename to nitrite/src/main/java/org/dizitart/no2/common/module/NitritePlugin.java index 0f08d5f0c..d15f52e1e 100644 --- a/nitrite/src/main/java/org/dizitart/no2/module/NitritePlugin.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/module/NitritePlugin.java @@ -14,13 +14,21 @@ * limitations under the License. */ -package org.dizitart.no2.module; +package org.dizitart.no2.common.module; import org.dizitart.no2.NitriteConfig; /** + * Represents a nitrite database plugin component. + * * @author Anindya Chatterjee. + * @since 4.0 */ public interface NitritePlugin { + /** + * Initializes the plugin instance. + * + * @param nitriteConfig the nitrite config + */ void initialize(NitriteConfig nitriteConfig); } diff --git a/nitrite/src/main/java/org/dizitart/no2/module/PluginManager.java b/nitrite/src/main/java/org/dizitart/no2/common/module/PluginManager.java similarity index 75% rename from nitrite/src/main/java/org/dizitart/no2/module/PluginManager.java rename to nitrite/src/main/java/org/dizitart/no2/common/module/PluginManager.java index d041e7ef8..61a53e8c3 100644 --- a/nitrite/src/main/java/org/dizitart/no2/module/PluginManager.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/module/PluginManager.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.dizitart.no2.module; +package org.dizitart.no2.common.module; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -22,8 +22,8 @@ import org.dizitart.no2.exceptions.NitriteIOException; import org.dizitart.no2.exceptions.PluginException; import org.dizitart.no2.index.*; -import org.dizitart.no2.mapper.MappableMapper; -import org.dizitart.no2.mapper.NitriteMapper; +import org.dizitart.no2.common.mapper.MappableMapper; +import org.dizitart.no2.common.mapper.NitriteMapper; import org.dizitart.no2.store.NitriteStore; import org.dizitart.no2.store.memory.InMemoryStoreModule; @@ -31,21 +31,37 @@ import java.util.Map; /** + * The nitrite database plugin manager. It loads the nitrite plugins + * before opening the database. + * + * @see NitriteModule + * @see NitritePlugin * @author Anindya Chatterjee. + * @since 4.0 */ @Slf4j @Getter public class PluginManager { - private final Map indexerMap; + private final Map indexerMap; private NitriteMapper nitriteMapper; private NitriteStore nitriteStore; private final NitriteConfig nitriteConfig; + /** + * Instantiates a new {@link PluginManager}. + * + * @param nitriteConfig the nitrite config + */ public PluginManager(NitriteConfig nitriteConfig) { this.indexerMap = new HashMap<>(); this.nitriteConfig = nitriteConfig; } + /** + * Loads a {@link NitriteModule} instance. + * + * @param module the module + */ public void loadModule(NitriteModule module) { if (module != null && module.plugins() != null) { for (NitritePlugin plugin : module.plugins()) { @@ -54,6 +70,9 @@ public void loadModule(NitriteModule module) { } } + /** + * Find and loads all nitrite plugins configured. + */ public void findAndLoadPlugins() { try { loadInternalPlugins(); @@ -63,6 +82,9 @@ public void findAndLoadPlugins() { } } + /** + * Initializes all plugins instances. + */ public void initializePlugins() { if (nitriteStore != null) { initializePlugin(nitriteStore); @@ -76,8 +98,8 @@ public void initializePlugins() { } if (!indexerMap.isEmpty()) { - for (Indexer indexer : indexerMap.values()) { - initializePlugin(indexer); + for (NitriteIndexer nitriteIndexer : indexerMap.values()) { + initializePlugin(nitriteIndexer); } } } @@ -117,28 +139,28 @@ private void loadIfNitriteMapper(NitritePlugin plugin) { } private synchronized void loadIfIndexer(NitritePlugin plugin) { - if (plugin instanceof Indexer) { - Indexer indexer = (Indexer) plugin; - if (indexerMap.containsKey(indexer.getIndexType())) { + if (plugin instanceof NitriteIndexer) { + NitriteIndexer nitriteIndexer = (NitriteIndexer) plugin; + if (indexerMap.containsKey(nitriteIndexer.getIndexType())) { throw new PluginException("multiple Indexer found for type " - + indexer.getIndexType()); + + nitriteIndexer.getIndexType()); } - this.indexerMap.put(indexer.getIndexType(), indexer); + this.indexerMap.put(nitriteIndexer.getIndexType(), nitriteIndexer); } } - private void loadInternalPlugins() { - if (!indexerMap.containsKey(IndexType.Unique)) { + protected void loadInternalPlugins() { + if (!indexerMap.containsKey(IndexType.UNIQUE)) { log.debug("Loading default unique indexer"); loadPlugin(new UniqueIndexer()); } - if (!indexerMap.containsKey(IndexType.NonUnique)) { + if (!indexerMap.containsKey(IndexType.NON_UNIQUE)) { log.debug("Loading default non-unique indexer"); loadPlugin(new NonUniqueIndexer()); } - if (!indexerMap.containsKey(IndexType.Fulltext)) { + if (!indexerMap.containsKey(IndexType.FULL_TEXT)) { log.debug("Loading nitrite text indexer"); loadPlugin(new NitriteTextIndexer()); } diff --git a/nitrite/src/main/java/org/dizitart/no2/common/processors/Processor.java b/nitrite/src/main/java/org/dizitart/no2/common/processors/Processor.java new file mode 100644 index 000000000..abad37dc6 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/processors/Processor.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.processors; + +import org.dizitart.no2.collection.Document; + +/** + * Represents a document processor. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +public interface Processor { + /** + * Processes a document before writing it into database. + * + * @param document the document + * @return the document + */ + Document processBeforeWrite(Document document); + + /** + * Processes a document after reading from the database. + * + * @param document the document + * @return the document + */ + Document processAfterRead(Document document); +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/processors/ProcessorChain.java b/nitrite/src/main/java/org/dizitart/no2/common/processors/ProcessorChain.java new file mode 100644 index 000000000..3d31ad18a --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/processors/ProcessorChain.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.processors; + +import org.dizitart.no2.collection.Document; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a {@link Processor} chain. It executes a + * list of processor on a document. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +public class ProcessorChain implements Processor { + private final List processors; + + /** + * Instantiates a new Processor chain. + */ + public ProcessorChain() { + processors = new ArrayList<>(); + } + + /** + * Adds a processor to the chain. + * + * @param processor the processor + */ + public void add(Processor processor) { + processors.add(processor); + } + + /** + * Removes a processor from the chain. + * + * @param processor the processor + */ + public void remove(Processor processor) { + processors.remove(processor); + } + + @Override + public Document processBeforeWrite(Document document) { + Document processed = document; + for (Processor processor : processors) { + processed = processor.processBeforeWrite(processed); + } + return processed; + } + + @Override + public Document processAfterRead(Document document) { + Document processed = document; + for (Processor processor : processors) { + processed = processor.processAfterRead(processed); + } + return processed; + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/processors/StringFieldEncryptionProcessor.java b/nitrite/src/main/java/org/dizitart/no2/common/processors/StringFieldEncryptionProcessor.java new file mode 100644 index 000000000..2d702b60b --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/processors/StringFieldEncryptionProcessor.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.processors; + +import lombok.extern.slf4j.Slf4j; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.crypto.AESEncryptor; +import org.dizitart.no2.common.crypto.Encryptor; +import org.dizitart.no2.common.util.StringUtils; +import org.dizitart.no2.exceptions.NitriteIOException; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * A string field encryption processor. It encrypts the field value + * of type {@link String} in a nitrite document using the provided {@link Encryptor}. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +@Slf4j +public class StringFieldEncryptionProcessor implements Processor { + private final Encryptor encryptor; + private final List fields; + + /** + * Instantiates a new {@link StringFieldEncryptionProcessor}. + * + * @param password the password + */ + public StringFieldEncryptionProcessor(String password) { + this(new AESEncryptor(password)); + } + + /** + * Instantiates a new {@link StringFieldEncryptionProcessor}. + * + * @param encryptor the encryptor + */ + public StringFieldEncryptionProcessor(Encryptor encryptor) { + this.encryptor = encryptor; + this.fields = new ArrayList<>(); + } + + /** + * Adds fields for encryption. + * + * @param fields the fields + */ + public void addFields(String... fields){ + this.fields.addAll(Arrays.asList(fields)); + } + + @Override + public Document processBeforeWrite(Document document) { + try { + Document copy = document.clone(); + if (!fields.isEmpty()) { + for (String field : fields) { + String value = copy.get(field, String.class); + if (!StringUtils.isNullOrEmpty(value)) { + // encrypt + value = encryptor.encrypt(value.getBytes(StandardCharsets.UTF_8)); + + // set the value + copy.put(field, value); + } + } + } + return copy; + } catch (Exception e) { + log.error("Error while processing document before write", e); + throw new NitriteIOException("failed to process document before write", e); + } + } + + @Override + public Document processAfterRead(Document document) { + try { + Document copy = document.clone(); + if (!fields.isEmpty()) { + for (String field : fields) { + String value = copy.get(field, String.class); + if (!StringUtils.isNullOrEmpty(value)) { + // decrypt + value = encryptor.decrypt(value); + + // set the value + copy.put(field, value); + } + } + } + return copy; + } catch (Exception e) { + log.error("Error while processing document after read", e); + throw new NitriteIOException("failed to process document after read", e); + } + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/streams/BoundedDocumentStream.java b/nitrite/src/main/java/org/dizitart/no2/common/streams/BoundedDocumentStream.java new file mode 100644 index 000000000..41a978163 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/streams/BoundedDocumentStream.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.streams; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.exceptions.ValidationException; + +import java.util.Collections; +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * Represents a bounded document stream. + * + * @since 1.0 + * @author Anindya Chatterjee. + */ +public class BoundedDocumentStream implements RecordStream> { + private final RecordStream> recordStream; + private final long skip; + private final long limit; + + /** + * Instantiates a new Bounded document stream. + * + * @param skip the skip + * @param limit the limit + * @param recordStream the record stream + */ + public BoundedDocumentStream(Long skip, Long limit, RecordStream> recordStream) { + this.skip = skip; + this.limit = limit; + + if (skip < 0) { + throw new ValidationException("skip parameter must not be negative"); + } + if (limit < 0) { + throw new ValidationException("limit parameter must not be negative"); + } + + this.recordStream = recordStream; + } + + @Override + public Iterator> iterator() { + Iterator> iterator = recordStream == null ? Collections.emptyIterator() + : recordStream.iterator(); + return new BoundedIterator<>(iterator, skip, limit); + } + + private static class BoundedIterator implements Iterator { + private final Iterator iterator; + private final long skip; + private final long limit; + private long pos; + + /** + * Instantiates a new Bounded iterator. + * + * @param iterator the iterator + * @param skip the skip + * @param limit the limit + */ + public BoundedIterator(final Iterator iterator, final long skip, final long limit) { + if (iterator == null) { + throw new ValidationException("iterator must not be null"); + } + if (skip < 0) { + throw new ValidationException("skip parameter must not be negative."); + } + if (limit < 0) { + throw new ValidationException("limit parameter must not be negative."); + } + + this.iterator = iterator; + this.skip = skip; + this.limit = limit; + pos = 0; + initialize(); + } + + private void initialize() { + while (pos < skip && iterator.hasNext()) { + iterator.next(); + pos++; + } + } + + @Override + public boolean hasNext() { + if (checkBounds()) { + return false; + } + return iterator.hasNext(); + } + + private boolean checkBounds() { + return pos - skip + 1 > limit; + } + + @Override + public T next() { + if (checkBounds()) { + throw new NoSuchElementException(); + } + final T next = iterator.next(); + pos++; + return next; + } + + @Override + public void remove() { + if (pos <= skip) { + throw new IllegalStateException("remove() cannot be called before calling next()"); + } + iterator.remove(); + } + } + +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/streams/DistinctStream.java b/nitrite/src/main/java/org/dizitart/no2/common/streams/DistinctStream.java new file mode 100644 index 000000000..7e23b041f --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/streams/DistinctStream.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.streams; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.tuples.Pair; + +import java.util.*; + +/** + * Represents a document stream of distinct elements + * + * @author Anindya Chatterjee + * @since 4.0 + */ +public class DistinctStream implements RecordStream> { + private final RecordStream> rawStream; + + /** + * Instantiates a new DistinctStream. + * + * @param rawStream the raw stream + */ + public DistinctStream(RecordStream> rawStream) { + this.rawStream = rawStream; + } + + @Override + public Iterator> iterator() { + Iterator> iterator = rawStream == null ? Collections.emptyIterator() + : rawStream.iterator(); + return new DistinctStreamIterator(iterator); + } + + private static class DistinctStreamIterator implements Iterator> { + private final Iterator> iterator; + private final Set scannedIds; + private Pair nextPair; + private boolean nextPairSet = false; + + /** + * Instantiates a new DistinctStreamIterator. + * + * @param iterator the iterator + */ + public DistinctStreamIterator(Iterator> iterator) { + this.iterator = iterator; + this.scannedIds = new HashSet<>(); // fastest lookup for ids - O(1) + } + + @Override + public boolean hasNext() { + return nextPairSet || setNextId(); + } + + @Override + public Pair next() { + if (!nextPairSet && !setNextId()) { + throw new NoSuchElementException(); + } + nextPairSet = false; + return nextPair; + } + + private boolean setNextId() { + while (iterator.hasNext()) { + final Pair pair = iterator.next(); + if (!scannedIds.contains(pair.getFirst())) { + scannedIds.add(pair.getFirst()); + nextPair = pair; + nextPairSet = true; + return true; + } + } + return false; + } + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/streams/DocumentSorter.java b/nitrite/src/main/java/org/dizitart/no2/common/streams/DocumentSorter.java new file mode 100644 index 000000000..c3b7307f6 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/streams/DocumentSorter.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.streams; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.DBNull; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.exceptions.ValidationException; + +import java.text.Collator; +import java.util.Comparator; +import java.util.List; + +/** + * Sorts documents based on the sort order provided. + * + *

    + * By default null is considered the lowest value. + *

    + * + * @author Anindya Chatterjee + * @since 4.0 + */ +public class DocumentSorter implements Comparator> { + private final Collator collator; + private final List> sortOrder; + + /** + * Instantiates a new Document sorter. + * + * @param collator the collator + * @param sortOrder the sort order + */ + public DocumentSorter(Collator collator, List> sortOrder) { + this.collator = collator; + this.sortOrder = sortOrder; + } + + @Override + @SuppressWarnings({"rawtypes", "unchecked"}) + public int compare(Pair pair1, Pair pair2) { + if (sortOrder != null && !sortOrder.isEmpty()) { + for (Pair pair : sortOrder) { + Document doc1 = pair1.getSecond(); + Document doc2 = pair2.getSecond(); + + Object value1 = doc1.get(pair.getFirst()); + Object value2 = doc2.get(pair.getFirst()); + + // handle null values + int result; + if ((value1 == null || value1 instanceof DBNull) && value2 != null) { + result = -1; + } else if (value1 != null && (value2 == null || value2 instanceof DBNull)) { + result = 1; + } else if (value1 == null) { + result = -1; + } else { + + // validate comparable + if (value1.getClass().isArray() || value1 instanceof Iterable + || value2.getClass().isArray() || value2 instanceof Iterable) { + throw new ValidationException("cannot sort on an array or collection object"); + } + + // compare values + Comparable c1 = (Comparable) value1; + Comparable c2 = (Comparable) value2; + + if (c1 instanceof String && c2 instanceof String && collator != null) { + result = collator.compare(c1, c2); + } else { + result = c1.compareTo(c2); + } + } + + if (pair.getSecond() == SortOrder.Descending) { + result *= -1; + } + + if (result != 0) { + return result; + } + } + } + return 0; + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/streams/DocumentStream.java b/nitrite/src/main/java/org/dizitart/no2/common/streams/DocumentStream.java new file mode 100644 index 000000000..66d61da9e --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/streams/DocumentStream.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.streams; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.Lookup; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.common.processors.ProcessorChain; + +import java.util.Collections; +import java.util.Iterator; + +/** + * Represents a nitrite document stream. + * + * @since 4.0 + * @author Anindya Chatterjee. + */ +public class DocumentStream implements DocumentCursor { + private final RecordStream> recordStream; + private final ProcessorChain processorChain; + + @Getter @Setter + private FindPlan findPlan; + + /** + * Instantiates a new Document stream. + * + * @param recordStream the record stream + * @param processorChain the processor chain + */ + public DocumentStream(RecordStream> recordStream, + ProcessorChain processorChain) { + this.recordStream = recordStream; + this.processorChain = processorChain; + } + + @Override + public RecordStream project(Document projection) { + validateProjection(projection); + return new ProjectedDocumentStream(recordStream, projection, processorChain); + } + + @Override + public RecordStream join(DocumentCursor foreignCursor, Lookup lookup) { + return new JoinedDocumentStream(recordStream, foreignCursor, lookup, processorChain); + } + + @Override + public Iterator iterator() { + Iterator> iterator = recordStream == null ? Collections.emptyIterator() + : recordStream.iterator(); + return new DocumentCursorIterator(iterator, processorChain); + } + + private void validateProjection(Document projection) { + for (Pair kvp : projection) { + validateKeyValuePair(kvp); + } + } + + private void validateKeyValuePair(Pair kvp) { + if (kvp.getSecond() != null) { + if (!(kvp.getSecond() instanceof Document)) { + throw new ValidationException("projection contains non-null values"); + } else { + validateProjection((Document) kvp.getSecond()); + } + } + } + + private static class DocumentCursorIterator implements Iterator { + private final Iterator> iterator; + private final ProcessorChain processorChain; + + /** + * Instantiates a new Document cursor iterator. + * + * @param iterator the iterator + * @param processorChain the processor chain + */ + DocumentCursorIterator(Iterator> iterator, + ProcessorChain processorChain) { + this.iterator = iterator; + this.processorChain = processorChain; + } + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public Document next() { + Pair next = iterator.next(); + Document document = next.getSecond(); + if (document != null) { + Document copy = document.clone(); + copy = processorChain.processAfterRead(copy); + return copy; + } + return null; + } + + @Override + public void remove() { + throw new InvalidOperationException("remove on cursor is not supported"); + } + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/streams/FilteredStream.java b/nitrite/src/main/java/org/dizitart/no2/common/streams/FilteredStream.java new file mode 100644 index 000000000..9c20ca7d3 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/streams/FilteredStream.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.streams; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.dizitart.no2.filters.Filter; + +import java.util.Collections; +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * Represents a filtered nitrite document stream. + * + * @author Anindya Chatterjee. + * @since 4.0 + */ +public class FilteredStream implements RecordStream> { + private final RecordStream> recordStream; + private final Filter filter; + + /** + * Instantiates a new Filtered stream. + * + * @param recordStream the record stream + * @param filter the filter + */ + public FilteredStream(RecordStream> recordStream, Filter filter) { + this.recordStream = recordStream; + this.filter = filter; + } + + @Override + public Iterator> iterator() { + Iterator> iterator = recordStream == null ? Collections.emptyIterator() + : recordStream.iterator(); + + // filter can be null from read operation when coll scan filter is null + if (filter == null || filter == Filter.ALL) { + return iterator; + } + return new FilteredIterator(iterator, filter); + } + + /** + * The type Filtered iterator. + */ + private static class FilteredIterator implements Iterator> { + private final Iterator> iterator; + private final Filter filter; + private Pair nextPair; + private boolean nextPairSet = false; + + /** + * Instantiates a new Filtered iterator. + * + * @param iterator the iterator + * @param filter the filter + */ + public FilteredIterator(Iterator> iterator, Filter filter) { + this.iterator = iterator; + this.filter = filter; + } + + @Override + public boolean hasNext() { + return nextPairSet || setNextId(); + } + + @Override + public Pair next() { + if (!nextPairSet && !setNextId()) { + throw new NoSuchElementException(); + } + nextPairSet = false; + return nextPair; + } + + @Override + public void remove() { + if (nextPairSet) { + throw new InvalidOperationException("remove operation cannot be called here"); + } + iterator.remove(); + } + + private boolean setNextId() { + while (iterator.hasNext()) { + final Pair pair = iterator.next(); + if (filter.apply(pair)) { + nextPair = pair; + nextPairSet = true; + return true; + } + } + return false; + } + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/streams/IndexedStream.java b/nitrite/src/main/java/org/dizitart/no2/common/streams/IndexedStream.java new file mode 100644 index 000000000..9bd99e034 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/streams/IndexedStream.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.streams; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.store.NitriteMap; + +import java.util.Iterator; +import java.util.Set; + +/** + * Represents a nitrite nitrite stream backed by an index. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +public class IndexedStream implements RecordStream> { + private final NitriteMap nitriteMap; + private final Set nitriteIds; + + /** + * Instantiates a new Indexed stream. + * + * @param nitriteIds the nitrite ids + * @param nitriteMap the nitrite map + */ + public IndexedStream(Set nitriteIds, + NitriteMap nitriteMap) { + this.nitriteIds = nitriteIds; + this.nitriteMap = nitriteMap; + } + + @Override + public Iterator> iterator() { + return new IndexedStreamIterator(nitriteIds.iterator(), nitriteMap); + } + + /** + * The type Indexed stream iterator. + */ + private static class IndexedStreamIterator implements Iterator> { + private final Iterator iterator; + private final NitriteMap nitriteMap; + + /** + * Instantiates a new Indexed stream iterator. + * + * @param iterator the iterator + * @param nitriteMap the nitrite map + */ + IndexedStreamIterator(Iterator iterator, + NitriteMap nitriteMap) { + this.iterator = iterator; + this.nitriteMap = nitriteMap; + } + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public Pair next() { + NitriteId id = iterator.next(); + Document document = nitriteMap.get(id); + return new Pair<>(id, document); + } + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/streams/JoinedDocumentStream.java b/nitrite/src/main/java/org/dizitart/no2/common/streams/JoinedDocumentStream.java new file mode 100644 index 000000000..633c37245 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/streams/JoinedDocumentStream.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.streams; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.Lookup; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.dizitart.no2.common.processors.ProcessorChain; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import static org.dizitart.no2.common.util.ObjectUtils.deepEquals; + +/** + * Represents a joined document stream. + * + * @author Anindya Chatterjee. + * @since 1.0 + */ +public class JoinedDocumentStream implements RecordStream { + private final RecordStream> recordStream; + private final DocumentCursor foreignCursor; + private final Lookup lookup; + private final ProcessorChain processorChain; + + /** + * Instantiates a new Joined document stream. + * + * @param recordStream the record stream + * @param foreignCursor the foreign cursor + * @param lookup the lookup + * @param processorChain the processor chain + */ + JoinedDocumentStream(RecordStream> recordStream, + DocumentCursor foreignCursor, + Lookup lookup, ProcessorChain processorChain) { + this.recordStream = recordStream; + this.foreignCursor = foreignCursor; + this.lookup = lookup; + this.processorChain = processorChain; + } + + + @Override + public Iterator iterator() { + Iterator> iterator = recordStream == null ? Collections.emptyIterator() + : recordStream.iterator(); + return new JoinedDocumentIterator(iterator, processorChain, foreignCursor, lookup); + } + + @Override + public String toString() { + return toList().toString(); + } + + private static class JoinedDocumentIterator implements Iterator { + private final Iterator> iterator; + private final ProcessorChain processorChain; + private final DocumentCursor foreignCursor; + private final Lookup lookup; + + /** + * Instantiates a new Joined document iterator. + * + * @param iterator the iterator + * @param processorChain the processor chain + */ + public JoinedDocumentIterator(Iterator> iterator, + ProcessorChain processorChain, + DocumentCursor foreignCursor, + Lookup lookup) { + this.iterator = iterator; + this.processorChain = processorChain; + this.foreignCursor = foreignCursor; + this.lookup = lookup; + } + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public Document next() { + Pair next = iterator.next(); + Document document = next.getSecond(); + if (document != null) { + Document unprocessed = document.clone(); + + // process the document + Document processed = processorChain.processAfterRead(unprocessed); + return join(processed, foreignCursor, lookup); + } + return null; + } + + @Override + public void remove() { + throw new InvalidOperationException("remove on a cursor is not supported"); + } + + private Document join(Document localDocument, DocumentCursor foreignCursor, Lookup lookup) { + Object localObject = localDocument.get(lookup.getLocalField()); + if (localObject == null) return localDocument; + Set target = new HashSet<>(); + + for (Document foreignDocument : foreignCursor) { + Object foreignObject = foreignDocument.get(lookup.getForeignField()); + if (foreignObject != null) { + if (deepEquals(foreignObject, localObject)) { + target.add(foreignDocument); + } + } + } + if (!target.isEmpty()) { + localDocument.put(lookup.getTargetField(), target); + } + return localDocument; + } + } +} + diff --git a/nitrite/src/main/java/org/dizitart/no2/common/streams/ProjectedDocumentStream.java b/nitrite/src/main/java/org/dizitart/no2/common/streams/ProjectedDocumentStream.java new file mode 100644 index 000000000..1905e35d4 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/streams/ProjectedDocumentStream.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.streams; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.dizitart.no2.common.processors.ProcessorChain; + +import java.util.Collections; +import java.util.Iterator; + +/** + * Represents a projected nitrite document stream. + * + * @author Anindya Chatterjee. + * @since 1.0 + */ +public class ProjectedDocumentStream implements RecordStream { + private final RecordStream> recordStream; + private final Document projection; + private final ProcessorChain processorChain; + + /** + * Instantiates a new Projected document stream. + * + * @param recordStream the record stream + * @param projection the projection + * @param processorChain the processor chain + */ + public ProjectedDocumentStream(RecordStream> recordStream, + Document projection, ProcessorChain processorChain) { + this.recordStream = recordStream; + this.projection = projection; + this.processorChain = processorChain; + } + + @Override + public Iterator iterator() { + Iterator> iterator = recordStream == null ? Collections.emptyIterator() + : recordStream.iterator(); + return new ProjectedDocumentIterator(iterator, processorChain, projection); + } + + @Override + public String toString() { + return toList().toString(); + } + + private static class ProjectedDocumentIterator implements Iterator { + private final Iterator> iterator; + private final ProcessorChain processorChain; + private Document nextElement = null; + private final Document projection; + + /** + * Instantiates a new Projected document iterator. + * + * @param iterator the iterator + * @param processorChain the processor chain + */ + ProjectedDocumentIterator(Iterator> iterator, + ProcessorChain processorChain, + Document projection) { + this.iterator = iterator; + this.processorChain = processorChain; + this.projection = projection; + nextMatch(); + } + + @Override + public boolean hasNext() { + return nextElement != null; + } + + @Override + public Document next() { + Document returnValue = nextElement.clone(); + nextMatch(); + return returnValue; + } + + private void nextMatch() { + while (iterator.hasNext()) { + Pair next = iterator.next(); + Document document = next.getSecond(); + if (document != null) { + Document projected = project(document.clone()); + if (projected != null) { + nextElement = projected; + return; + } + } + } + + nextElement = null; + } + + @Override + public void remove() { + throw new InvalidOperationException("remove on a cursor is not supported"); + } + + private Document project(Document original) { + if (projection == null) return original; + Document result = original.clone(); + + for (Pair pair : original) { + if (!projection.containsKey(pair.getFirst())) { + result.remove(pair.getFirst()); + } + } + + // process the result + result = processorChain.processAfterRead(result); + return result; + } + } +} + diff --git a/nitrite/src/main/java/org/dizitart/no2/common/streams/SortedDocumentStream.java b/nitrite/src/main/java/org/dizitart/no2/common/streams/SortedDocumentStream.java new file mode 100644 index 000000000..8c89985c2 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/streams/SortedDocumentStream.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.streams; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.common.util.Iterables; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +/** + * Represents a sorted nitrite document stream + * + * @since 4.0 + * @author Anindya Chatterjee. + */ +public class SortedDocumentStream implements RecordStream> { + private final FindPlan findPlan; + private final RecordStream> recordStream; + + public SortedDocumentStream(FindPlan findPlan, + RecordStream> recordStream) { + this.findPlan = findPlan; + this.recordStream = recordStream; + } + + @Override + public Iterator> iterator() { + if (recordStream == null) return Collections.emptyIterator(); + + DocumentSorter documentSorter = new DocumentSorter(findPlan.getCollator(), + findPlan.getBlockingSortOrder()); + + List> recordList = Iterables.toList(recordStream); + Collections.sort(recordList, documentSorter); + + return recordList.iterator(); + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/streams/UnionStream.java b/nitrite/src/main/java/org/dizitart/no2/common/streams/UnionStream.java new file mode 100644 index 000000000..1be91dc60 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/streams/UnionStream.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.streams; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.tuples.Pair; + +import java.util.*; + +/** + * Represents an union of multiple distinct nitrite document stream. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +public class UnionStream implements RecordStream> { + private final Collection>> streams; + + /** + * Instantiates a new Union stream. + * + * @param streams the streams + */ + public UnionStream(Collection>> streams) { + this.streams = streams; + } + + @Override + public Iterator> iterator() { + Queue>> iteratorQueue = new LinkedList<>(); + for (RecordStream> stream : streams) { + iteratorQueue.add(stream.iterator()); + } + return new UnionStreamIterator(iteratorQueue); + } + + /** + * The type Union stream iterator. + */ + private static class UnionStreamIterator implements Iterator> { + private final Queue>> iteratorQueue; + private Iterator> currentIterator; + + /** + * Instantiates a new Union stream iterator. + * + * @param iteratorQueue the iterator queue + */ + public UnionStreamIterator(Queue>> iteratorQueue) { + this.iteratorQueue = iteratorQueue; + } + + @Override + public boolean hasNext() { + updateCurrentIterator(); + return currentIterator.hasNext(); + } + + @Override + public Pair next() { + updateCurrentIterator(); + return currentIterator.next(); + } + + + private void updateCurrentIterator() { + if (currentIterator == null) { + if (iteratorQueue.isEmpty()) { + currentIterator = Collections.emptyIterator(); + } else { + currentIterator = iteratorQueue.remove(); + } + } + + while (!currentIterator.hasNext() && !iteratorQueue.isEmpty()) { + currentIterator = iteratorQueue.remove(); + } + } + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/tuples/Pair.java b/nitrite/src/main/java/org/dizitart/no2/common/tuples/Pair.java index 45fcf6a63..cf2298ad9 100644 --- a/nitrite/src/main/java/org/dizitart/no2/common/tuples/Pair.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/tuples/Pair.java @@ -28,6 +28,8 @@ /** * Represents a pair. * + * @param the type parameter + * @param the type parameter * @author Anindya Chatterjee. * @since 4.0 */ @@ -40,6 +42,19 @@ public class Pair implements Serializable { private A first; private B second; + /** + * Creates a new pair. + * + * @param the type parameter + * @param the type parameter + * @param first the first + * @param second the second + * @return the pair + */ + public static Pair pair(A first, B second) { + return new Pair<>(first, second); + } + private void writeObject(ObjectOutputStream stream) throws IOException { stream.writeObject(first); stream.writeObject(second); diff --git a/nitrite/src/main/java/org/dizitart/no2/common/tuples/Quartet.java b/nitrite/src/main/java/org/dizitart/no2/common/tuples/Quartet.java index 6ce5b86ae..6fb0cb6d7 100644 --- a/nitrite/src/main/java/org/dizitart/no2/common/tuples/Quartet.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/tuples/Quartet.java @@ -10,7 +10,14 @@ import java.io.Serializable; /** + * Represents a quartet. + * + * @param the type parameter + * @param the type parameter + * @param the type parameter + * @param the type parameter * @author Anindya Chatterjee + * @since 4.0 */ @Data @NoArgsConstructor @@ -23,6 +30,23 @@ public class Quartet implements Serializable { private C third; private D fourth; + /** + * Creates a new quartet. + * + * @param the type parameter + * @param the type parameter + * @param the type parameter + * @param the type parameter + * @param a the a + * @param b the b + * @param c the c + * @param d the d + * @return the quartet + */ + public static Quartet quartet(A a, B b, C c, D d) { + return new Quartet<>(a, b, c, d); + } + private void writeObject(ObjectOutputStream stream) throws IOException { stream.writeObject(first); stream.writeObject(second); diff --git a/nitrite/src/main/java/org/dizitart/no2/common/tuples/Quintet.java b/nitrite/src/main/java/org/dizitart/no2/common/tuples/Quintet.java index 811e76473..be33599f4 100644 --- a/nitrite/src/main/java/org/dizitart/no2/common/tuples/Quintet.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/tuples/Quintet.java @@ -10,7 +10,15 @@ import java.io.Serializable; /** + * Represents a quintet. + * + * @param the type parameter + * @param the type parameter + * @param the type parameter + * @param the type parameter + * @param the type parameter * @author Anindya Chatterjee + * @since 4.0 */ @Data @NoArgsConstructor @@ -24,6 +32,25 @@ public class Quintet implements Serializable { private D fourth; private E fifth; + /** + * Creates a new quintet. + * + * @param the type parameter + * @param the type parameter + * @param the type parameter + * @param the type parameter + * @param the type parameter + * @param a the a + * @param b the b + * @param c the c + * @param d the d + * @param e the e + * @return the quintet + */ + public static Quintet quintet(A a, B b, C c, D d, E e) { + return new Quintet<>(a, b, c, d, e); + } + private void writeObject(ObjectOutputStream stream) throws IOException { stream.writeObject(first); stream.writeObject(second); diff --git a/nitrite/src/main/java/org/dizitart/no2/common/tuples/Triplet.java b/nitrite/src/main/java/org/dizitart/no2/common/tuples/Triplet.java index cd77853ed..d0ce767c0 100644 --- a/nitrite/src/main/java/org/dizitart/no2/common/tuples/Triplet.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/tuples/Triplet.java @@ -12,6 +12,9 @@ /** * Represents a triplet. * + * @param the type parameter + * @param the type parameter + * @param the type parameter * @author Anindya Chatterjee. * @since 4.0 */ @@ -25,6 +28,21 @@ public class Triplet implements Serializable { private B second; private C third; + /** + * Creates a new triplet. + * + * @param the type parameter + * @param the type parameter + * @param the type parameter + * @param a the a + * @param b the b + * @param c the c + * @return the triplet + */ + public static Triplet triplet(A a, B b, C c) { + return new Triplet<>(a, b, c); + } + private void writeObject(ObjectOutputStream stream) throws IOException { stream.writeObject(first); stream.writeObject(second); diff --git a/nitrite/src/main/java/org/dizitart/no2/common/util/Base64.java b/nitrite/src/main/java/org/dizitart/no2/common/util/Base64.java new file mode 100644 index 000000000..f27ddcfaf --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/util/Base64.java @@ -0,0 +1,550 @@ +package org.dizitart.no2.common.util; + +import java.nio.charset.StandardCharsets; + +/** + * Utilities for encoding and decoding the Base64 representation of + * binary data. + * + *

    + * This is a derivative work of android.util.Base64 class + * from Android Open Source Project + *

    + * + * @since 4.0 + * @author The Android Open Source Project + * @author Anindya Chatterjee + */ +public class Base64 { + /** + * Encoder flag bit to omit the padding '=' characters at the end + * of the output (if any). + */ + public static final int NO_PADDING = 1; + /** + * Encoder flag bit to omit all line terminators (i.e., the output + * will be on one long line). + */ + public static final int NO_WRAP = 2; + /** + * Encoder flag bit to indicate lines should be terminated with a + * CRLF pair instead of just an LF. Has no effect if {@code + * NO_WRAP} is specified as well. + */ + public static final int CRLF = 4; + /** + * Encoder/decoder flag bit to indicate using the "URL and + * filename safe" variant of Base64 (see RFC 3548 section 4) where + * {@code -} and {@code _} are used in place of {@code +} and + * {@code /}. + */ + public static final int URL_SAFE = 8; + + static abstract class Coder { + public byte[] output; + public int op; + } + // -------------------------------------------------------- + // decoding + // -------------------------------------------------------- + + /** + * Decode the Base64-encoded data in input and return the data in + * a new byte array. + * + *

    The padding '=' characters at the end are considered optional, but + * if any are present, there must be the correct number of them. + * + * @param input the input array to decode + * @param flags controls certain features of the decoded output. + * Pass {@code DEFAULT} to decode standard Base64. + * + * @throws IllegalArgumentException if the input contains + * incorrect padding + */ + public static byte[] decode(byte[] input, int flags) { + return decode(input, 0, input.length, flags); + } + /** + * Decode the Base64-encoded data in input and return the data in + * a new byte array. + * + *

    The padding '=' characters at the end are considered optional, but + * if any are present, there must be the correct number of them. + * + * @param input the data to decode + * @param offset the position within the input array at which to start + * @param len the number of bytes of input to decode + * @param flags controls certain features of the decoded output. + * Pass {@code DEFAULT} to decode standard Base64. + * + * @throws IllegalArgumentException if the input contains + * incorrect padding + */ + public static byte[] decode(byte[] input, int offset, int len, int flags) { + // Allocate space for the most data the input could represent. + // (It could contain less if it contains whitespace, etc.) + Decoder decoder = new Decoder(flags, new byte[len*3/4]); + if (!decoder.process(input, offset, len)) { + throw new IllegalArgumentException("bad base-64"); + } + // Maybe we got lucky and allocated exactly enough output space. + if (decoder.op == decoder.output.length) { + return decoder.output; + } + // Need to shorten the array, so allocate a new one of the + // right size and copy. + byte[] temp = new byte[decoder.op]; + System.arraycopy(decoder.output, 0, temp, 0, decoder.op); + return temp; + } + /* package */ static class Decoder extends Coder { + /** + * Lookup table for turning bytes into their position in the + * Base64 alphabet. + */ + private static final int[] DECODE = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }; + /** + * Decode lookup table for the "web safe" variant (RFC 3548 + * sec. 4) where - and _ replace + and /. + */ + private static final int[] DECODE_WEBSAFE = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }; + /** Non-data values in the DECODE arrays. */ + private static final int SKIP = -1; + private static final int EQUALS = -2; + /** + * States 0-3 are reading through the next input tuple. + * State 4 is having read one '=' and expecting exactly + * one more. + * State 5 is expecting no more data or padding characters + * in the input. + * State 6 is the error state; an error has been detected + * in the input and no future input can "fix" it. + */ + private int state; // state number (0 to 6) + private final int value; + final private int[] alphabet; + public Decoder(int flags, byte[] output) { + this.output = output; + alphabet = ((flags & URL_SAFE) == 0) ? DECODE : DECODE_WEBSAFE; + state = 0; + value = 0; + } + + /** + * Decode another block of input data. + * + * @return true if the state machine is still healthy. false if + * bad base-64 data has been detected in the input stream. + */ + private boolean process(byte[] input, int offset, int len) { + if (this.state == 6) return false; + int p = offset; + len += offset; + // Using local variables makes the decoder about 12% + // faster than if we manipulate the member variables in + // the loop. (Even alphabet makes a measurable + // difference, which is somewhat surprising to me since + // the member variable is final.) + int state = this.state; + int value = this.value; + int op = 0; + final byte[] output = this.output; + final int[] alphabet = this.alphabet; + while (p < len) { + // Try the fast path: we're starting a new tuple and the + // next four bytes of the input stream are all data + // bytes. This corresponds to going through states + // 0-1-2-3-0. We expect to use this method for most of + // the data. + // + // If any of the next four bytes of input are non-data + // (whitespace, etc.), value will end up negative. (All + // the non-data values in decode are small negative + // numbers, so shifting any of them up and or'ing them + // together will result in a value with its top bit set.) + // + // You can remove this whole block and the output should + // be the same, just slower. + if (state == 0) { + while (p+4 <= len && + (value = ((alphabet[input[p] & 0xff] << 18) | + (alphabet[input[p+1] & 0xff] << 12) | + (alphabet[input[p+2] & 0xff] << 6) | + (alphabet[input[p+3] & 0xff]))) >= 0) { + output[op+2] = (byte) value; + output[op+1] = (byte) (value >> 8); + output[op] = (byte) (value >> 16); + op += 3; + p += 4; + } + if (p >= len) break; + } + // The fast path isn't available -- either we've read a + // partial tuple, or the next four input bytes aren't all + // data, or whatever. Fall back to the slower state + // machine implementation. + int d = alphabet[input[p++] & 0xff]; + switch (state) { + case 0: + if (d >= 0) { + value = d; + ++state; + } else if (d != SKIP) { + this.state = 6; + return false; + } + break; + case 1: + if (d >= 0) { + value = (value << 6) | d; + ++state; + } else if (d != SKIP) { + this.state = 6; + return false; + } + break; + case 2: + if (d >= 0) { + value = (value << 6) | d; + ++state; + } else if (d == EQUALS) { + // Emit the last (partial) output tuple; + // expect exactly one more padding character. + output[op++] = (byte) (value >> 4); + state = 4; + } else if (d != SKIP) { + this.state = 6; + return false; + } + break; + case 3: + if (d >= 0) { + // Emit the output triple and return to state 0. + value = (value << 6) | d; + output[op+2] = (byte) value; + output[op+1] = (byte) (value >> 8); + output[op] = (byte) (value >> 16); + op += 3; + state = 0; + } else if (d == EQUALS) { + // Emit the last (partial) output tuple; + // expect no further data or padding characters. + output[op+1] = (byte) (value >> 2); + output[op] = (byte) (value >> 10); + op += 2; + state = 5; + } else if (d != SKIP) { + this.state = 6; + return false; + } + break; + case 4: + if (d == EQUALS) { + ++state; + } else if (d != SKIP) { + this.state = 6; + return false; + } + break; + case 5: + if (d != SKIP) { + this.state = 6; + return false; + } + break; + } + } + // Done reading input. Now figure out where we are left in + // the state machine and finish up. + switch (state) { + case 0: + // Output length is a multiple of three. Fine. + break; + case 1: + case 4: + // Read one padding '=' when we expected 2. Illegal. + // Read one extra input byte, which isn't enough to + // make another output byte. Illegal. + this.state = 6; + return false; + case 2: + // Read two extra input bytes, enough to emit 1 more + // output byte. Fine. + output[op++] = (byte) (value >> 4); + break; + case 3: + // Read three extra input bytes, enough to emit 2 more + // output bytes. Fine. + output[op++] = (byte) (value >> 10); + output[op++] = (byte) (value >> 2); + break; + case 5: + // Read all the padding '='s we expected and no more. + // Fine. + break; + } + this.state = state; + this.op = op; + return true; + } + } + // -------------------------------------------------------- + // encoding + // -------------------------------------------------------- + /** + * Base64-encode the given data and return a newly allocated + * String with the result. + * + * @param input the data to encode + * @param flags controls certain features of the encoded output. + * Passing {@code DEFAULT} results in output that + * adheres to RFC 2045. + */ + public static String encodeToString(byte[] input, int flags) { + return new String(encode(input, flags), StandardCharsets.US_ASCII); + } + + /** + * Base64-encode the given data and return a newly allocated + * byte[] with the result. + * + * @param input the data to encode + * @param flags controls certain features of the encoded output. + * Passing {@code DEFAULT} results in output that + * adheres to RFC 2045. + */ + public static byte[] encode(byte[] input, int flags) { + return encode(input, 0, input.length, flags); + } + /** + * Base64-encode the given data and return a newly allocated + * byte[] with the result. + * + * @param input the data to encode + * @param offset the position within the input array at which to + * start + * @param len the number of bytes of input to encode + * @param flags controls certain features of the encoded output. + * Passing {@code DEFAULT} results in output that + * adheres to RFC 2045. + */ + public static byte[] encode(byte[] input, int offset, int len, int flags) { + Encoder encoder = new Encoder(flags, null); + // Compute the exact length of the array we will produce. + int output_len = len / 3 * 4; + // Account for the tail of the data and the padding bytes, if any. + if (encoder.do_padding) { + if (len % 3 > 0) { + output_len += 4; + } + } else { + switch (len % 3) { + case 0: break; + case 1: output_len += 2; break; + case 2: output_len += 3; break; + } + } + // Account for the newlines, if any. + if (encoder.do_newline && len > 0) { + output_len += (((len-1) / (3 * Encoder.LINE_GROUPS)) + 1) * + (encoder.do_cr ? 2 : 1); + } + encoder.output = new byte[output_len]; + encoder.process(input, offset, len); + assert encoder.op == output_len; + return encoder.output; + } + + static class Encoder extends Coder { + /** + * Emit a new line every this many output tuples. Corresponds to + * a 76-character line length (the maximum allowable according to + * RFC 2045). + */ + public static final int LINE_GROUPS = 19; + /** + * Lookup table for turning Base64 alphabet positions (6 bits) + * into output bytes. + */ + private static final byte[] ENCODE = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', + }; + /** + * Lookup table for turning Base64 alphabet positions (6 bits) + * into output bytes. + */ + private static final byte[] ENCODE_WEBSAFE = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_', + }; + final private byte[] tail; + int tailLen; + private int count; + final public boolean do_padding; + final public boolean do_newline; + final public boolean do_cr; + final private byte[] alphabet; + public Encoder(int flags, byte[] output) { + this.output = output; + do_padding = (flags & NO_PADDING) == 0; + do_newline = (flags & NO_WRAP) == 0; + do_cr = (flags & CRLF) != 0; + alphabet = ((flags & URL_SAFE) == 0) ? ENCODE : ENCODE_WEBSAFE; + tail = new byte[2]; + tailLen = 0; + count = do_newline ? LINE_GROUPS : -1; + } + + private void process(byte[] input, int offset, int len) { + // Using local variables makes the encoder about 9% faster. + final byte[] alphabet = this.alphabet; + final byte[] output = this.output; + int op = 0; + int count = this.count; + int p = offset; + len += offset; + int v = -1; + // First we need to concatenate the tail of the previous call + // with any input bytes available now and see if we can empty + // the tail. + switch (tailLen) { + case 0: + // There was no tail. + break; + case 1: + if (p+2 <= len) { + // A 1-byte tail with at least 2 bytes of + // input available now. + v = ((tail[0] & 0xff) << 16) | + ((input[p++] & 0xff) << 8) | + (input[p++] & 0xff); + tailLen = 0; + }; + break; + case 2: + if (p+1 <= len) { + // A 2-byte tail with at least 1 byte of input. + v = ((tail[0] & 0xff) << 16) | + ((tail[1] & 0xff) << 8) | + (input[p++] & 0xff); + tailLen = 0; + } + break; + } + if (v != -1) { + output[op++] = alphabet[(v >> 18) & 0x3f]; + output[op++] = alphabet[(v >> 12) & 0x3f]; + output[op++] = alphabet[(v >> 6) & 0x3f]; + output[op++] = alphabet[v & 0x3f]; + if (--count == 0) { + if (do_cr) output[op++] = '\r'; + output[op++] = '\n'; + count = LINE_GROUPS; + } + } + // At this point either there is no tail, or there are fewer + // than 3 bytes of input available. + // The main loop, turning 3 input bytes into 4 output bytes on + // each iteration. + while (p+3 <= len) { + v = ((input[p] & 0xff) << 16) | + ((input[p+1] & 0xff) << 8) | + (input[p+2] & 0xff); + output[op] = alphabet[(v >> 18) & 0x3f]; + output[op+1] = alphabet[(v >> 12) & 0x3f]; + output[op+2] = alphabet[(v >> 6) & 0x3f]; + output[op+3] = alphabet[v & 0x3f]; + p += 3; + op += 4; + if (--count == 0) { + if (do_cr) output[op++] = '\r'; + output[op++] = '\n'; + count = LINE_GROUPS; + } + } + // Finish up the tail of the input. Note that we need to + // consume any bytes in tail before any bytes + // remaining in input; there should be at most two bytes + // total. + if (p-tailLen == len-1) { + int t = 0; + v = ((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 4; + tailLen -= t; + output[op++] = alphabet[(v >> 6) & 0x3f]; + output[op++] = alphabet[v & 0x3f]; + if (do_padding) { + output[op++] = '='; + output[op++] = '='; + } + if (do_newline) { + if (do_cr) output[op++] = '\r'; + output[op++] = '\n'; + } + } else if (p-tailLen == len-2) { + int t = 0; + v = (((tailLen > 1 ? tail[t++] : input[p++]) & 0xff) << 10) | + (((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 2); + tailLen -= t; + output[op++] = alphabet[(v >> 12) & 0x3f]; + output[op++] = alphabet[(v >> 6) & 0x3f]; + output[op++] = alphabet[v & 0x3f]; + if (do_padding) { + output[op++] = '='; + } + if (do_newline) { + if (do_cr) output[op++] = '\r'; + output[op++] = '\n'; + } + } else if (do_newline && op > 0 && count != LINE_GROUPS) { + if (do_cr) output[op++] = '\r'; + output[op++] = '\n'; + } + assert tailLen == 0; + assert p == len; + this.op = op; + this.count = count; + } + } + + private Base64() { } // don't instantiate +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/util/Comparables.java b/nitrite/src/main/java/org/dizitart/no2/common/util/Comparables.java index 3dbfeac71..0c13bcd20 100644 --- a/nitrite/src/main/java/org/dizitart/no2/common/util/Comparables.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/util/Comparables.java @@ -1,11 +1,21 @@ package org.dizitart.no2.common.util; /** + * A utility class for comparables. + * + * @since 1.0 * @author Anindya Chatterjee */ public class Comparables { private Comparables() {} + /** + * Compares two comparable objects. + * + * @param first the first + * @param second the second + * @return the int + */ @SuppressWarnings({"rawtypes", "unchecked"}) public static int compare(Comparable first, Comparable second) { if (first instanceof Number && second instanceof Number) { diff --git a/nitrite/src/main/java/org/dizitart/no2/common/util/CryptoUtils.java b/nitrite/src/main/java/org/dizitart/no2/common/util/CryptoUtils.java new file mode 100644 index 000000000..5081e78d0 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/util/CryptoUtils.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.util; + +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.SecretKeySpec; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; + +/** + * A utility class for cryptographic operations + * + * @since 4.0 + * @author Anindya Chatterjee + */ +public class CryptoUtils { + + /** + * Gets random nonce. + * + * @param numBytes the number of bytes + * @return the byte [ ] + */ + public static byte[] getRandomNonce(int numBytes) { + byte[] nonce = new byte[numBytes]; + new SecureRandom().nextBytes(nonce); + return nonce; + } + + /** + * Gets password derived AES 256 bits secret key + * + * @param password the password + * @param salt the salt + * @return the aes key from password + * @throws NoSuchAlgorithmException the no such algorithm exception + * @throws InvalidKeySpecException the invalid key spec exception + */ + public static SecretKey getAESKeyFromPassword(char[] password, byte[] salt) + throws NoSuchAlgorithmException, InvalidKeySpecException { + + SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); + // iterationCount = 65536 + // keyLength = 256 + KeySpec spec = new PBEKeySpec(password, salt, 65536, 256); + return new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES"); + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/util/DocumentUtils.java b/nitrite/src/main/java/org/dizitart/no2/common/util/DocumentUtils.java index 17648771f..9c92db1ab 100644 --- a/nitrite/src/main/java/org/dizitart/no2/common/util/DocumentUtils.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/util/DocumentUtils.java @@ -17,10 +17,13 @@ package org.dizitart.no2.common.util; import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.FieldValues; +import org.dizitart.no2.common.Fields; import org.dizitart.no2.common.tuples.Pair; import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.mapper.NitriteMapper; +import org.dizitart.no2.common.mapper.NitriteMapper; +import java.util.ArrayList; import java.util.Objects; import static org.dizitart.no2.common.util.ObjectUtils.newInstance; @@ -87,6 +90,20 @@ public static boolean isSimilar(Document document, Document other, String... fie return result; } + public static FieldValues getValues(Document document, Fields fields) { + FieldValues fieldValues = new FieldValues(); + fieldValues.setNitriteId(document.getId()); + fieldValues.setFields(fields); + fieldValues.setValues(new ArrayList<>()); + + for (String field : fields.getFieldNames()) { + Object value = document.get(field); + fieldValues.getValues().add(new Pair<>(field, value)); + } + + return fieldValues; + } + private static Document removeValues(Document document) { if (document == null) return null; for (Pair entry : document) { diff --git a/nitrite/src/main/java/org/dizitart/no2/common/util/IndexUtils.java b/nitrite/src/main/java/org/dizitart/no2/common/util/IndexUtils.java new file mode 100644 index 000000000..bfb9413b1 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/common/util/IndexUtils.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.util; + +import org.dizitart.no2.index.IndexDescriptor; + +import static org.dizitart.no2.common.Constants.*; + +/** + * A utility class for index. + * + * @author Anindya Chatterjee + * @since 1.0 + */ +public class IndexUtils { + private IndexUtils() {} + + /** + * Derives index map name. + * + * @param descriptor the descriptor + * @return the string + */ + public static String deriveIndexMapName(IndexDescriptor descriptor) { + return INDEX_PREFIX + + INTERNAL_NAME_SEPARATOR + + descriptor.getCollectionName() + + INTERNAL_NAME_SEPARATOR + + descriptor.getIndexFields().getEncodedName() + + INTERNAL_NAME_SEPARATOR + + descriptor.getIndexType(); + } + + /** + * Derives index meta map name. + * + * @param collectionName the collection name + * @return the string + */ + public static String deriveIndexMetaMapName(String collectionName) { + return INDEX_META_PREFIX + INTERNAL_NAME_SEPARATOR + collectionName; + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/common/util/Iterables.java b/nitrite/src/main/java/org/dizitart/no2/common/util/Iterables.java index f106d68f7..55b980d91 100644 --- a/nitrite/src/main/java/org/dizitart/no2/common/util/Iterables.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/util/Iterables.java @@ -16,6 +16,8 @@ package org.dizitart.no2.common.util; +import org.dizitart.no2.common.UnknownType; + import java.lang.reflect.Array; import java.util.*; @@ -59,7 +61,7 @@ public static List toList(Iterable iterable) { for (T item : iterable) { list.add(item); } - return Collections.unmodifiableList(list); + return list; } /** @@ -75,7 +77,7 @@ public static Set toSet(Iterable iterable) { for (T item : iterable) { set.add(item); } - return Collections.unmodifiableSet(set); + return set; } /** @@ -115,6 +117,15 @@ public static List listOf(T... items) { return Collections.emptyList(); } + @SafeVarargs + public static Set setOf(T... items) { + Set set = new HashSet<>(); + if (items != null) { + set.addAll(Arrays.asList(items)); + } + return set; + } + public static long size(Iterable iterable) { if (iterable instanceof Collection) { return ((Collection) iterable).size(); @@ -127,6 +138,15 @@ public static long size(Iterable iterable) { return count; } + public static Class getElementType(Iterable iterable) { + if (iterable == null) return UnknownType.class; + Iterator iterator = iterable.iterator(); + if (iterator.hasNext()) { + return iterator.next().getClass(); + } + return UnknownType.class; + } + @SuppressWarnings({"unchecked", "rawtypes"}) static Object[] toArray(Iterable iterable) { if (iterable instanceof Collection) { diff --git a/nitrite/src/main/java/org/dizitart/no2/common/util/SecureString.java b/nitrite/src/main/java/org/dizitart/no2/common/util/SecureString.java index 84bc098a3..bad6e4899 100644 --- a/nitrite/src/main/java/org/dizitart/no2/common/util/SecureString.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/util/SecureString.java @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2017-2020. Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.util; import java.security.SecureRandom; @@ -7,7 +23,10 @@ * This is not a string but a CharSequence that can be cleared of its memory. * Important for handling passwords. Represents text that should be kept * confidential, such as by deleting it from computer memory when no longer - * needed or garbaged collected. + * needed or garbage collected. + * + * @since 4.0 + * @author Anindya Chatterjee */ public class SecureString implements CharSequence { diff --git a/nitrite/src/main/java/org/dizitart/no2/common/util/StringUtils.java b/nitrite/src/main/java/org/dizitart/no2/common/util/StringUtils.java index 607a8786e..0659cdf00 100644 --- a/nitrite/src/main/java/org/dizitart/no2/common/util/StringUtils.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/util/StringUtils.java @@ -16,6 +16,7 @@ package org.dizitart.no2.common.util; +import java.util.Arrays; import java.util.StringTokenizer; /** @@ -58,6 +59,10 @@ public static boolean isNullOrEmpty(CharSequence value) { * @since 4.0.0 */ public static String join(String separator, String[] strings) { + return join(separator, Arrays.asList(strings)); + } + + public static String join(String separator, Iterable strings) { StringBuilder sb = new StringBuilder(); int end = 0; for (String s : strings) { diff --git a/nitrite/src/main/java/org/dizitart/no2/common/util/ValidationUtils.java b/nitrite/src/main/java/org/dizitart/no2/common/util/ValidationUtils.java index ca3a4f17d..60afea147 100644 --- a/nitrite/src/main/java/org/dizitart/no2/common/util/ValidationUtils.java +++ b/nitrite/src/main/java/org/dizitart/no2/common/util/ValidationUtils.java @@ -16,7 +16,6 @@ package org.dizitart.no2.common.util; -import org.dizitart.no2.collection.Document; import org.dizitart.no2.exceptions.IndexingException; import org.dizitart.no2.exceptions.InvalidOperationException; import org.dizitart.no2.exceptions.ValidationException; @@ -72,6 +71,12 @@ public static void notEmpty(Collection value, String message) { } } + public static void notEmpty(T[] value, String message) { + if (value.length == 0) { + throw new ValidationException(message); + } + } + /** * Validates if an object is `null`. * @@ -99,31 +104,11 @@ public static void containsNull(T[] array, String message) { } } - /** - * Validates if a field of a document can be indexed. - * - * @param fieldValue the field value - * @param field the field - */ - public static void validateDocumentIndexField(Object fieldValue, String field) { - if (fieldValue == null) return; - - if (fieldValue instanceof Document) { - throw new InvalidOperationException("compound index on field " + field + " is not supported"); - } - - if (!(fieldValue instanceof Iterable || fieldValue.getClass().isArray())) { - if (!(fieldValue instanceof Comparable)) { - throw new IndexingException("cannot index on non comparable field " + field); - } - } - } - public static void validateIterableIndexField(Iterable fieldValue, String field) { if (fieldValue != null) { for (Object value : fieldValue) { if (value == null) continue; - validateArrayItem(value, field); + validateArrayIndexItem(value, field); } } } @@ -142,7 +127,7 @@ public static void validateArrayIndexField(Object arrayValue, String field) { Object[] array = convertToObjectArray(arrayValue); for (Object value : array) { if (value == null) continue; - validateArrayItem(value, field); + validateArrayIndexItem(value, field); } } } @@ -157,7 +142,26 @@ public static void validateStringArrayIndexField(Object arrayValue, String field } } - private static void validateArrayItem(Object value, String field) { + public static void validateFilterArrayField(Object arrayValue, String field) { + if (arrayValue != null) { + Object[] array = convertToObjectArray(arrayValue); + for (Object value : array) { + if (value == null) continue; + validateArrayFilterItem(value, field); + } + } + } + + public static void validateFilterIterableField(Iterable fieldValue, String field) { + if (fieldValue != null) { + for (Object value : fieldValue) { + if (value == null) continue; + validateArrayFilterItem(value, field); + } + } + } + + private static void validateArrayIndexItem(Object value, String field) { if (value instanceof Iterable || value.getClass().isArray()) { throw new InvalidOperationException("nested array index on iterable field " + field + " is not supported"); } @@ -176,4 +180,14 @@ private static void validateStringArrayItem(Object value, String field) { throw new IndexingException("cannot index on an array field containing non string values " + field); } } + + private static void validateArrayFilterItem(Object value, String field) { + if (value instanceof Iterable || value.getClass().isArray()) { + throw new InvalidOperationException("nested array is not supported"); + } + + if (!(value instanceof Comparable)) { + throw new IndexingException("cannot filter using non comparable values " + field); + } + } } diff --git a/nitrite/src/main/java/org/dizitart/no2/exceptions/MigrationException.java b/nitrite/src/main/java/org/dizitart/no2/exceptions/MigrationException.java index ec613b355..2980689dd 100644 --- a/nitrite/src/main/java/org/dizitart/no2/exceptions/MigrationException.java +++ b/nitrite/src/main/java/org/dizitart/no2/exceptions/MigrationException.java @@ -1,9 +1,17 @@ package org.dizitart.no2.exceptions; /** + * Exception thrown when a migration step fails. + * * @author Anindya Chatterjee + * @since 4.0 */ public class MigrationException extends NitriteException { + /** + * Instantiates a new Migration exception. + * + * @param errorMessage the error message + */ public MigrationException(String errorMessage) { super(errorMessage); } diff --git a/nitrite/src/main/java/org/dizitart/no2/exceptions/NitriteSecurityException.java b/nitrite/src/main/java/org/dizitart/no2/exceptions/NitriteSecurityException.java new file mode 100644 index 000000000..df5a7b173 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/exceptions/NitriteSecurityException.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017-2020. Nitrite author or authors. + * + * Licensed 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.dizitart.no2.exceptions; + +/** + * Exception thrown when a database security error occurs. + * + * @author Anindya Chatterjee. + * @since 1.0 + */ +public class NitriteSecurityException extends NitriteException { + /** + * Instantiates a new {@link NitriteSecurityException}. + * + * @param errorMessage the error message + */ + public NitriteSecurityException(String errorMessage) { + super(errorMessage); + } + + /** + * Instantiates a new {@link NitriteSecurityException}. + * + * @param errorMessage the error message + * @param cause the cause + */ + public NitriteSecurityException(String errorMessage, Throwable cause) { + super(errorMessage, cause); + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/exceptions/PluginException.java b/nitrite/src/main/java/org/dizitart/no2/exceptions/PluginException.java index 74ad3bcac..6363b7cac 100644 --- a/nitrite/src/main/java/org/dizitart/no2/exceptions/PluginException.java +++ b/nitrite/src/main/java/org/dizitart/no2/exceptions/PluginException.java @@ -17,13 +17,27 @@ package org.dizitart.no2.exceptions; /** + * Exception thrown when a nitrite plugin fails to load properly. + * * @author Anindya Chatterjee. + * @since 4.0 */ public class PluginException extends NitriteException { + /** + * Instantiates a new Plugin exception. + * + * @param errorMessage the error message + */ public PluginException(String errorMessage) { super(errorMessage); } + /** + * Instantiates a new Plugin exception. + * + * @param errorMessage the error message + * @param cause the cause + */ public PluginException(String errorMessage, Throwable cause) { super(errorMessage, cause); } diff --git a/nitrite/src/main/java/org/dizitart/no2/exceptions/SecurityException.java b/nitrite/src/main/java/org/dizitart/no2/exceptions/SecurityException.java deleted file mode 100644 index 4f5106ab8..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/exceptions/SecurityException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.exceptions; - -/** - * Exception thrown when a database security error occurs. - * - * @author Anindya Chatterjee. - * @since 1.0 - */ -public class SecurityException extends NitriteException { - /** - * Instantiates a new {@link SecurityException}. - * - * @param errorMessage the error message - */ - public SecurityException(String errorMessage) { - super(errorMessage); - } -} diff --git a/nitrite/src/main/java/org/dizitart/no2/exceptions/TransactionException.java b/nitrite/src/main/java/org/dizitart/no2/exceptions/TransactionException.java index cf76276e6..ac4757488 100644 --- a/nitrite/src/main/java/org/dizitart/no2/exceptions/TransactionException.java +++ b/nitrite/src/main/java/org/dizitart/no2/exceptions/TransactionException.java @@ -1,13 +1,27 @@ package org.dizitart.no2.exceptions; /** + * Exception thrown when a transaction fails. + * * @author Anindya Chatterjee + * @since 4.0 */ public class TransactionException extends NitriteException { + /** + * Instantiates a new Transaction exception. + * + * @param errorMessage the error message + */ public TransactionException(String errorMessage) { super(errorMessage); } + /** + * Instantiates a new Transaction exception. + * + * @param errorMessage the error message + * @param error the error + */ public TransactionException(String errorMessage, Throwable error) { super(errorMessage, error); } diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/AndFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/AndFilter.java index 8b70cb6c6..9e646111b 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/AndFilter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/AndFilter.java @@ -22,33 +22,52 @@ import org.dizitart.no2.common.tuples.Pair; import org.dizitart.no2.exceptions.FilterException; -import java.util.Arrays; -import java.util.List; - /** + * Represents an And filter. + * * @author Anindya Chatterjee + * @since 1.0 */ @Getter public class AndFilter extends LogicalFilter { - private final Filter rhs; - private final Filter lhs; - AndFilter(Filter lhs, Filter rhs) { - this.lhs = lhs; - this.rhs = rhs; + /** + * Instantiates a new And filter. + * + * @param filters the filters + */ + AndFilter(Filter... filters) { + super(filters); - if (rhs instanceof TextFilter) { - throw new FilterException("text filter must be the first filter in and operation"); + for (int i = 1; i < filters.length; i++) { + if (filters[i] instanceof TextFilter) { + throw new FilterException("text filter must be the first filter in AND operation"); + } } } @Override public boolean apply(Pair element) { - return lhs.apply(element) && rhs.apply(element); + boolean result = true; + for (Filter filter : getFilters()) { + result = result && filter.apply(element); + } + return result; } @Override - public List getFilters() { - return Arrays.asList(lhs, rhs); + public String toString() { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("("); + for (int i = 0; i < getFilters().size(); i++) { + Filter filter = getFilters().get(i); + if (i == 0) { + stringBuilder.append(filter.toString()); + } else { + stringBuilder.append(" && ").append(filter.toString()); + } + } + stringBuilder.append(")"); + return stringBuilder.toString(); } } diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/BetweenFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/BetweenFilter.java index 4a2e6731d..a8693caf6 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/BetweenFilter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/BetweenFilter.java @@ -58,6 +58,10 @@ private static void validateBound(Bound bound) { } } + @Override + public String toString() { + return super.toString(); + } @Data public static class Bound { diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/ComparableArrayFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/ComparableArrayFilter.java new file mode 100644 index 000000000..abf104623 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/filters/ComparableArrayFilter.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.filters; + +import org.dizitart.no2.common.mapper.NitriteMapper; + +import static org.dizitart.no2.common.util.ValidationUtils.*; + +/** + * @author Anindya Chatterjee + */ +abstract class ComparableArrayFilter extends ComparableFilter { + /** + * Instantiates a new Comparable filter. + * + * @param field the field + * @param value the value + */ + public ComparableArrayFilter(String field, Object value) { + super(field, value); + } + + @Override + protected void validateSearchTerm(NitriteMapper nitriteMapper, String field, Object value) { + notNull(field, "field cannot be null"); + notEmpty(field, "field cannot be empty"); + + if (value != null) { + if (value.getClass().isArray()) { + validateFilterArrayField(value, field); + } else if (value instanceof Iterable) { + validateFilterIterableField((Iterable) value, field); + } + } + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/ComparableFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/ComparableFilter.java new file mode 100644 index 000000000..e2d7c64fc --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/filters/ComparableFilter.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2017-2020. Nitrite author or authors. + * + * Licensed 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.dizitart.no2.filters; + +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.index.IndexMap; + +import java.util.List; +import java.util.NavigableMap; + +/** + * Represents a filter based on document field holding {@link Comparable} values. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +public abstract class ComparableFilter extends FieldBasedFilter { + /** + * Instantiates a new Comparable filter. + * + * @param field the field + * @param value the value + */ + public ComparableFilter(String field, Object value) { + super(field, value); + } + + /** + * Gets the {@link Comparable} value to filter. + * + * @return the comparable + */ + @SuppressWarnings("rawtypes") + public Comparable getComparable() { + if (getValue() == null) { + throw new FilterException("value parameter must not be null"); + } + return (Comparable) getValue(); + } + + /** + * Apply this filter on an nitrite index. + * + * @param indexMap the index scanner + * @return the object + */ + public abstract List applyOnIndex(IndexMap indexMap); + + /** + * Process values after index scanning. + * + * @param value the value + * @param subMap the sub map + * @param nitriteIds the nitrite ids + */ + @SuppressWarnings("unchecked") + protected void processIndexValue(Object value, + List, Object>> subMap, + List nitriteIds) { + if (value instanceof List) { + // if its is list then add it directly to nitrite ids + List result = (List) value; + nitriteIds.addAll(result); + } + + if (value instanceof NavigableMap) { + subMap.add((NavigableMap, Object>) value); + } + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/ComparisonFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/ComparisonFilter.java deleted file mode 100644 index 633330425..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/filters/ComparisonFilter.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.filters; - -import org.dizitart.no2.exceptions.FilterException; - -/** - * @author Anindya Chatterjee - */ -abstract class ComparisonFilter extends IndexAwareFilter { - protected ComparisonFilter(String field, Comparable value) { - super(field, value); - } - - @SuppressWarnings("rawtypes") - public Comparable getComparable() { - if (getValue() == null) { - throw new FilterException("value parameter must not be null"); - } - return (Comparable) getValue(); - } -} diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/ElementMatchFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/ElementMatchFilter.java index b2c99269c..842d303fd 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/ElementMatchFilter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/ElementMatchFilter.java @@ -76,6 +76,11 @@ public boolean apply(Pair element) { } } + @Override + public String toString() { + return "elemMatch(" + field + " : " + elementFilter.toString() + ")"; + } + @SuppressWarnings("rawtypes") private boolean matches(Iterable iterable, Filter filter) { for (Object item : iterable) { @@ -284,4 +289,6 @@ private boolean matchRegex(Object item, Filter filter) { throw new FilterException(item + " is not a string"); } } + + } diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/EqualsFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/EqualsFilter.java index ec6807b04..c290f4896 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/EqualsFilter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/EqualsFilter.java @@ -16,64 +16,24 @@ package org.dizitart.no2.filters; -import lombok.ToString; import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.index.ComparableIndexer; -import org.dizitart.no2.index.TextIndexer; -import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.index.IndexMap; -import java.util.LinkedHashSet; -import java.util.Set; +import java.util.ArrayList; +import java.util.List; import static org.dizitart.no2.common.util.ObjectUtils.deepEquals; /** * @author Anindya Chatterjee. */ -@ToString -class EqualsFilter extends IndexAwareFilter { +public class EqualsFilter extends ComparableFilter { EqualsFilter(String field, Object value) { super(field, value); } - @Override - @SuppressWarnings("rawtypes") - protected Set findIndexedIdSet() { - Set idSet = new LinkedHashSet<>(); - if (getIsFieldIndexed()) { - if (getValue() == null || getValue() instanceof Comparable) { - if (getIndexer() instanceof ComparableIndexer) { - ComparableIndexer comparableIndexer = (ComparableIndexer) getIndexer(); - idSet = comparableIndexer.findEqual(getCollectionName(), getField(), (Comparable) getValue()); - } else if (getIndexer() instanceof TextIndexer && getValue() instanceof String) { - // eq filter is not compatible with TextIndexer - setIsFieldIndexed(false); - } else { - throw new FilterException("eq filter is not supported on indexed field " - + getField()); - } - } else { - throw new FilterException(getValue() + " is not comparable"); - } - } - return idSet; - } - - @Override - protected Set findIdSet(NitriteMap collection) { - Set idSet = new LinkedHashSet<>(); - if (getOnIdField() && getValue() instanceof String) { - NitriteId nitriteId = NitriteId.createId((String) getValue()); - if (collection.containsKey(nitriteId)) { - idSet.add(nitriteId); - } - } - return idSet; - } - @Override public boolean apply(Pair element) { Document document = element.getSecond(); @@ -82,9 +42,19 @@ public boolean apply(Pair element) { } @Override - public void setIsFieldIndexed(Boolean isFieldIndexed) { - if (!(getIndexer() instanceof TextIndexer && getValue() instanceof String)) { - super.setIsFieldIndexed(isFieldIndexed); + public List applyOnIndex(IndexMap indexMap) { + Object value = indexMap.get((Comparable) getValue()); + if (value instanceof List) { + return ((List) value); } + + List result = new ArrayList<>(); + result.add(value); + return result; + } + + @Override + public String toString() { + return "(" + getField() + " == " + getValue() + ")"; } } diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/FieldBasedFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/FieldBasedFilter.java index 06a160a68..9112d515e 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/FieldBasedFilter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/FieldBasedFilter.java @@ -20,18 +20,17 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.Getter; -import org.dizitart.no2.exceptions.FilterException; import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.util.HashSet; -import java.util.Set; +import org.dizitart.no2.common.mapper.NitriteMapper; import static org.dizitart.no2.common.util.ValidationUtils.notEmpty; import static org.dizitart.no2.common.util.ValidationUtils.notNull; /** + * Represents a filter based on value of a nitrite document field. + * * @author Anindya Chatterjee + * @since 4.0 */ @Data @EqualsAndHashCode(callSuper = true) @@ -44,34 +43,22 @@ public abstract class FieldBasedFilter extends NitriteFilter { @Getter(AccessLevel.NONE) private boolean processed = false; + /** + * Instantiates a new Field based filter. + * + * @param field the field + * @param value the value + */ protected FieldBasedFilter(String field, Object value) { this.field = field; this.value = value; } - protected Set> convertValues(Set> values) { - if (getObjectFilter()) { - NitriteMapper nitriteMapper = getNitriteConfig().nitriteMapper(); - Set> convertedValues = new HashSet<>(); - - for (Comparable comparable : values) { - if (comparable == null - || !nitriteMapper.isValue(comparable)) { - throw new FilterException("search term " + comparable - + " is not a comparable"); - } - - if (nitriteMapper.isValue(comparable)) { - Comparable convertValue = nitriteMapper.convert(comparable, Comparable.class); - convertedValues.add(convertValue); - } - } - - return convertedValues; - } - return values; - } - + /** + * Gets the value fo the filter. + * + * @return the value + */ public Object getValue() { if (this.processed) return value; @@ -89,7 +76,7 @@ public Object getValue() { return value; } - private void validateSearchTerm(NitriteMapper nitriteMapper, String field, Object value) { + protected void validateSearchTerm(NitriteMapper nitriteMapper, String field, Object value) { notNull(field, "field cannot be null"); notEmpty(field, "field cannot be empty"); diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/Filter.java b/nitrite/src/main/java/org/dizitart/no2/filters/Filter.java index bbec9084a..bb884ff63 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/Filter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/Filter.java @@ -20,164 +20,25 @@ import org.dizitart.no2.collection.NitriteCollection; import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.exceptions.FilterException; import static org.dizitart.no2.common.Constants.DOC_ID; +import static org.dizitart.no2.common.util.ValidationUtils.notEmpty; /** * An interface to specify filtering criteria during find operation. When * a filter is applied to a collection, based on the criteria it returns - * a set of {@link NitriteId}s of matching records. + * a set of matching records. *

    * Each filtering criteria is based on a value of a document. If the value * is indexed, the find operation takes the advantage of it and only scans * the index map for that value. But if the value is not indexed, it scans * the whole collection. - *

    - * The supported filters are: - *

    - * .Comparison Filters - * [width="80%",cols="2,4,10"] - * |=== - * |Filter |Method |Description - *

    - * |Equals - * |{@link FluentFilter#eq(Object)} - * |Matches values that are equal to a specified value. - *

    - * |Greater - * |{@link FluentFilter#gt(Comparable)} - * |Matches values that are greater than a specified value. - *

    - * |GreaterEquals - * |{@link FluentFilter#gte(Comparable)} - * |Matches values that are greater than or equal to a specified value. - *

    - * |Lesser - * |{@link FluentFilter#lt(Comparable)} - * |Matches values that are less than a specified value. - *

    - * |LesserEquals - * |{@link FluentFilter#lte(Comparable)} - * |Matches values that are less than or equal to a specified value. - *

    - * |In - * |{@link FluentFilter#in(Comparable[])} - * |Matches any of the values specified in an array. - * |=== - *

    - * .Logical Filters - * [width="80%",cols="2,4,10"] - * |=== - * |Filter |Method |Description - *

    - * |Not - * |{@link Filter#not()} - * |Inverts the effect of a filter and returns results that do not match the filter. - *

    - * |Or - * |{@link Filter#or(Filter)} - * |Joins filters with a logical OR returns all ids of the documents that match the conditions - * of either filter. - *

    - * |And - * |{@link Filter#and(Filter)} - * |Joins filters with a logical AND returns all ids of the documents that match the conditions - * of both filters. - * |=== - *

    - * .Array Filter - * [width="80%",cols="2,4,10"] - * |=== - * |Filter |Method |Description - *

    - * |Element Match - * |{@link FluentFilter#elemMatch(Filter)} - * |Matches documents that contain an array field with at least one element that matches - * the specified filter. - * |=== - *

    - * .Text Filters - * [width="80%",cols="2,4,10"] - * |=== - * |Filter |Method |Description - *

    - * |Text - * |{@link FluentFilter#text(String)} - * |Performs full-text search. - *

    - * |Regex - * |{@link FluentFilter#regex(String)} - * |Selects documents where values match a specified regular expression. - * |=== - *

    - * [[app-listing]] - * [source,java] - * .Example of various filters - * -- - *

    - * // returns the ids of the documents whose age field value is 30 - * collection.find(where("age").eq(30)); - *

    - * // age field value is greater than 30 - * collection.find(where("age").gt(30)); - *

    - * // age field value is not 30 - * collection.find(where("age").eq(30).not())); - *

    - * // age field value is 30 and salary greater than 10K - * collection.find(where("age").eq(30).and(where("salary").gt(10000))); - *

    - * // note field contains the string 'hello' - * collection.find(where("note").regex("hello")); - *

    - * // prices field contains price value between 10 to 20 - * collection.find(where("prices").elemMatch($.gt(10).and($.lt(20)))); - *

    - * -- - *

    - * A nitrite document can contain another document. To specify a field - * of a nested document a '.' operator is used. If a field is an array - * or list, array/list index can be used as a field to access a specific - * element in them. - *

    - * [[app-listing]] - * [source,java] - * .Example of nested document - * -- - * NitriteMapper nitriteMapper = new JacksonMapper(); - *

    - * // parse a json into a document - * doc = nitriteMapper.parse("{" + - * " score: 1034," + - * " location: { " + - * " state: 'NY', " + - * " city: 'New York', " + - * " address: {" + - * " line1: '40', " + - * " line2: 'ABC Street', " + - * " house: ['1', '2', '3'] " + - * " }" + - * " }," + - * " category: ['food', 'produce', 'grocery'], " + - * " objArray: [{ field: 1}, {field: 2}]" + - * "}"); - *

    - * // insert the doc into collection - * collection.insert(doc); - *

    - * // filter on nested document - * collection.find(where("location.address.line1").eq("40")); - *

    - * // filter on array using array index - * collection.find(where("location.address.house.2").eq("3")); - *

    - * // filter on object array - * collection.find(where("objArray.0.field").eq(1)); - *

    - * -- + *

    * * @author Anindya Chatterjee - * @see NitriteCollection#find(Filter) + * @see NitriteCollection#find(Filter) NitriteCollection#find(Filter) + * @see NitriteCollection#find(Filter, org.dizitart.no2.collection.FindOptions) NitriteCollection#find(Filter, org.dizitart.no2.collection.FindOptions) * @since 1.0 */ public interface Filter { @@ -186,71 +47,59 @@ public interface Filter { */ Filter ALL = element -> true; + /** + * Filter by id. + * + * @param nitriteId the nitrite id + * @return the filter + */ static Filter byId(NitriteId nitriteId) { return new EqualsFilter(DOC_ID, nitriteId.getIdValue()); } /** - * Filters a document map and returns the set of {@link NitriteId}s of - * matching {@link Document}s. + * And filter. * - * @param element the {@link org.dizitart.no2.store.NitriteMap} entry to check. - * @return a set of {@link NitriteId}s of matching documents. + * @param filters the filters + * @return the filter */ - boolean apply(Pair element); + static Filter and(Filter... filters) { + notEmpty(filters, "at least two filters must be specified"); + if (filters.length < 2) { + throw new FilterException("at least two filters must be specified"); + } + + return new AndFilter(filters); + } /** - * Creates an and filter which performs a logical AND operation on two filters and selects - * the documents that satisfy both filters. - *

    - * [[app-listing]] - * [source,java] - * .Example - * -- - * // matches all documents where 'age' field has value as 30 and - * // 'name' field has value as John Doe - * collection.find(where("age").eq(30).and(where("name").eq("John Doe"))); - * -- + * Or filter. * - * @param filter other filter - * @return the and filter + * @param filters the filters + * @return the filter */ - default Filter and(Filter filter) { - return new AndFilter(this, filter); + static Filter or(Filter... filters) { + notEmpty(filters, "at least two filters must be specified"); + if (filters.length < 2) { + throw new FilterException("at least two filters must be specified"); + } + + return new OrFilter(filters); } /** - * Creates an or filter which performs a logical OR operation on two filters and selects - * the documents that satisfy at least one of the filter. - *

    - * [[app-listing]] - * [source,java] - * .Example - * -- - * // matches all documents where 'age' field has value as 30 or - * // 'name' field has value as John Doe - * collection.find(where("age").eq(30).or(where("name").eq("John Doe"))); - * -- + * Filters a document map and returns true if the criteria matches. * - * @param filter other filter - * @return the or filter + * @param element the entry to check. + * @return boolean value to indicate if the filtering criteria matches the document. */ - default Filter or(Filter filter) { - return new OrFilter(this, filter); - } + boolean apply(Pair element); /** - * Creates a not filter which performs a logical NOT operation on a `filter` and selects - * the documents that *_do not_* satisfy the `filter`. This also includes documents + * Creates a not filter which performs a logical NOT operation on a filter and selects + * the documents that *_do not_* satisfy the criteria. This also includes documents * that do not contain the value. *

    - * [[app-listing]] - * [source,java] - * .Example - * -- - * // matches all documents where 'age' field has value not equals to 30 - * collection.find(where("age").eq("age").not()); - * -- * * @return the not filter */ diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/FluentFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/FluentFilter.java index 0ca71a42f..98d7d00bb 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/FluentFilter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/FluentFilter.java @@ -16,18 +16,29 @@ package org.dizitart.no2.filters; -import org.dizitart.no2.index.TextIndexer; - /** + * A fluent api for the {@link Filter}. + * * @author Anindya Chatterjee. + * @since 4.0 */ public final class FluentFilter { + /** + * The where clause for elemMatch filter. + */ public static FluentFilter $ = where("$"); + private String field; private FluentFilter() { } + /** + * Where clause for fluent filter. + * + * @param field the field + * @return the fluent filter + */ public static FluentFilter where(String field) { FluentFilter filter = new FluentFilter(); filter.field = field; @@ -37,99 +48,67 @@ public static FluentFilter where(String field) { /** * Creates an equality filter which matches documents where the value * of a field equals the specified value. - *

    - * [[app-listing]] - * [source,java] - * .Example - * -- - * // matches all documents where 'age' field has value as 30 - * collection.find(where("age").eq(30)); - * -- + * * * @param value the value * @return the equality filter. */ - public Filter eq(Object value) { + public NitriteFilter eq(Object value) { return new EqualsFilter(field, value); } - public Filter notEq(Object value) { + /** + * Creates an equality filter which matches documents where the value + * of a field not equals the specified value. + * + * @param value the value + * @return the filter + */ + public NitriteFilter notEq(Object value) { return new NotEqualsFilter(field, value); } /** * Creates a greater than filter which matches those documents where the value * of the field is greater than (i.e. >) the specified value. - *

    - * [[app-listing]] - * [source,java] - * .Example - * -- - * // matches all documents where 'age' field has value greater than 30 - * collection.find(where("age").gt(30)); - * -- * * @param value the value * @return the greater than filter */ - public Filter gt(Comparable value) { + public NitriteFilter gt(Comparable value) { return new GreaterThanFilter(field, value); } /** * Creates a greater equal filter which matches those documents where the value * of the field is greater than or equals to (i.e. ≥) the specified value. - *

    - * [[app-listing]] - * [source,java] - * .Example - * -- - * // matches all documents where 'age' field has value greater than or equal to 30 - * collection.find(where("age").gte(30)); - * -- * * @param value the value * @return the greater or equal filter */ - public Filter gte(Comparable value) { + public NitriteFilter gte(Comparable value) { return new GreaterEqualFilter(field, value); } /** * Creates a lesser than filter which matches those documents where the value * of the field is less than (i.e. <) the specified value. - *

    - * [[app-listing]] - * [source,java] - * .Example - * -- - * // matches all documents where 'age' field has value less than 30 - * collection.find(where("age").lt(30)); - * -- * * @param value the value * @return the lesser than filter */ - public Filter lt(Comparable value) { + public NitriteFilter lt(Comparable value) { return new LesserThanFilter(field, value); } /** * Creates a lesser equal filter which matches those documents where the value * of the field is lesser than or equals to (i.e. ≤) the specified value. - *

    - * [[app-listing]] - * [source,java] - * .Example - * -- - * // matches all documents where 'age' field has value lesser than or equal to 30 - * collection.find(where("age").lte(30)); - * -- * * @param value the value * @return the lesser equal filter */ - public Filter lte(Comparable value) { + public NitriteFilter lte(Comparable value) { return new LesserEqualFilter(field, value); } @@ -139,14 +118,14 @@ public Filter lte(Comparable value) { *

     {@code
          * // matches all documents where 'age' field is between 30 and 40
          * collection.find(where("age").between(40, 30));
    -     * }
    +     * }*
          * 
    * * @param lowerBound the lower value * @param upperBound the upper value * @return the between filter */ - public Filter between(Comparable lowerBound, Comparable upperBound) { + public NitriteFilter between(Comparable lowerBound, Comparable upperBound) { return new BetweenFilter<>(field, new BetweenFilter.Bound<>(lowerBound, upperBound)); } @@ -157,15 +136,15 @@ public Filter between(Comparable lowerBound, Comparable upperBound) { * // matches all documents where 'age' field is * // between 30 and 40, excluding 30 and 40 * collection.find(where("age").between(40, 30, false)); - * } + * }* * * * @param lowerBound the lower value * @param upperBound the upper value - * @param inclusive indicates whether to include end values + * @param inclusive indicates whether to include end values * @return the between filter */ - public Filter between(Comparable lowerBound, Comparable upperBound, boolean inclusive) { + public NitriteFilter between(Comparable lowerBound, Comparable upperBound, boolean inclusive) { return new BetweenFilter<>(field, new BetweenFilter.Bound<>(lowerBound, upperBound, inclusive)); } @@ -176,115 +155,75 @@ public Filter between(Comparable lowerBound, Comparable upperBound, boolea * // matches all documents where 'age' field is * // between 30 and 40, including 40 and excluding 30 * collection.find(where("age").between(40, 30, true, false)); - * } + * }* * * - * @param lowerBound the lower value - * @param upperBound the upper value + * @param lowerBound the lower value + * @param upperBound the upper value * @param lowerInclusive indicates whether to include lower end value * @param upperInclusive indicates whether to include upper end value * @return the between filter */ - public Filter between(Comparable lowerBound, Comparable upperBound, boolean lowerInclusive, boolean upperInclusive) { - return new BetweenFilter<>(field, new BetweenFilter.Bound<>(lowerBound, upperBound, lowerInclusive, upperInclusive + public NitriteFilter between(Comparable lowerBound, Comparable upperBound, + boolean lowerInclusive, boolean upperInclusive) { + return new BetweenFilter<>(field, + new BetweenFilter.Bound<>(lowerBound, upperBound, lowerInclusive, upperInclusive )); } /** * Creates a text filter which performs a text search on the content of the fields * indexed with a full-text index. - *

    - * [[app-listing]] - * [source,java] - * .Example - * -- - * // matches all documents where 'address' field has value 'roads'. - * collection.find(where("address").text("roads")); - * -- * * @param value the text value * @return the text filter - * @see TextIndexer * @see org.dizitart.no2.index.fulltext.TextTokenizer */ - public Filter text(String value) { + public NitriteFilter text(String value) { return new TextFilter(field, value); } /** * Creates a string filter which provides regular expression capabilities * for pattern matching strings in documents. - *

    - * [[app-listing]] - * [source,java] - * .Example - * -- - * // matches all documents where 'name' value starts with 'jim' or 'joe'. - * collection.find(where("address").regex("^(jim|joe).*")); - * -- * * @param value the regular expression * @return the regex filter */ - public Filter regex(String value) { + public NitriteFilter regex(String value) { return new RegexFilter(field, value); } /** * Creates an in filter which matches the documents where * the value of a field equals any value in the specified array. - *

    - * [[app-listing]] - * [source,java] - * .Example - * -- - * // matches all documents where 'age' field has value in [20, 30, 40] - * collection.find(where("age").in(20, 30, 40)); - * -- * * @param values the range values * @return the in filter */ - public Filter in(Comparable... values) { + public NitriteFilter in(Comparable... values) { return new InFilter(field, values); } /** * Creates a notIn filter which matches the documents where * the value of a field not equals any value in the specified array. - *

    - * [[app-listing]] - * [source,java] - * .Example - * -- - * // matches all documents where 'age' field has value not in [20, 30, 40] - * collection.find(where("age").notIn(20, 30, 40)); - * -- * * @param values the range values * @return the notIn filter */ - public Filter notIn(Comparable... values) { + public NitriteFilter notIn(Comparable... values) { return new NotInFilter(field, values); } /** * Creates an element match filter that matches documents that contain an array - * value with at least one element that matches the specified `filter`. - *

    - * [[app-listing]] - * [source,java] - * .Example - * -- - * // matches all documents which has an array field - 'color' and the array - * // contains a value - 'red'. - * collection.find(where("age").elemMatch($.eq("red"))); - * -- + * value with at least one element that matches the specified filter. * * @param filter the filter to satisfy * @return the element match filter */ - public Filter elemMatch(Filter filter) { + public NitriteFilter elemMatch(Filter filter) { return new ElementMatchFilter(field, filter); } } diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/GreaterEqualFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/GreaterEqualFilter.java index 73c5a8802..f3c8374bb 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/GreaterEqualFilter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/GreaterEqualFilter.java @@ -20,47 +20,22 @@ import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.common.tuples.Pair; import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.index.ComparableIndexer; -import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.index.IndexMap; -import java.util.LinkedHashSet; -import java.util.Set; +import java.util.ArrayList; +import java.util.List; +import java.util.NavigableMap; import static org.dizitart.no2.common.util.Numbers.compare; /** * @author Anindya Chatterjee */ -class GreaterEqualFilter extends ComparisonFilter { +class GreaterEqualFilter extends ComparableFilter { GreaterEqualFilter(String field, Comparable value) { super(field, value); } - @Override - @SuppressWarnings("rawtypes") - protected Set findIndexedIdSet() { - Set idSet = new LinkedHashSet<>(); - if (getIsFieldIndexed()) { - if (getIndexer() instanceof ComparableIndexer && getValue() instanceof Comparable) { - ComparableIndexer comparableIndexer = (ComparableIndexer) getIndexer(); - idSet = comparableIndexer.findGreaterEqual(getCollectionName(), getField(), (Comparable) getValue()); - } else { - if (getValue() instanceof Comparable) { - throw new FilterException("gte filter is not supported on indexed field " - + getField()); - } else { - throw new FilterException(getValue() + " is not comparable"); - } - } - } - return idSet; - } - - @Override - protected Set findIdSet(NitriteMap collection) { - throw new FilterException("gte filter cannot be applied on _id field"); - } - @Override @SuppressWarnings({"unchecked", "rawtypes"}) public boolean apply(Pair element) { @@ -80,4 +55,38 @@ public boolean apply(Pair element) { return false; } + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + public List applyOnIndex(IndexMap indexMap) { + Comparable comparable = getComparable(); + List, Object>> subMap = new ArrayList<>(); + + // maintain the find sorting order + List nitriteIds = new ArrayList<>(); + + Comparable ceilingKey = indexMap.ceilingKey(comparable); + while (ceilingKey != null) { + // get the starting value, it can be a navigable-map (compound index) + // or list (single field index) + Object value = indexMap.get(ceilingKey); + processIndexValue(value, subMap, nitriteIds); + + ceilingKey = indexMap.higherKey(ceilingKey); + } + + if (!subMap.isEmpty()) { + // if sub-map is populated then filtering on compound index, return sub-map + return subMap; + } else { + // else it is filtering on either single field index, + // or it is a terminal filter on compound index, return only nitrite-ids + return nitriteIds; + } + } + + @Override + public String toString() { + return "(" + getField() + " >= " + getValue() + ")"; + } } diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/GreaterThanFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/GreaterThanFilter.java index 58681e9b4..a41b71a92 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/GreaterThanFilter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/GreaterThanFilter.java @@ -20,46 +20,22 @@ import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.common.tuples.Pair; import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.index.ComparableIndexer; -import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.index.IndexMap; -import java.util.LinkedHashSet; -import java.util.Set; +import java.util.ArrayList; +import java.util.List; +import java.util.NavigableMap; import static org.dizitart.no2.common.util.Numbers.compare; /** * @author Anindya Chatterjee */ -class GreaterThanFilter extends ComparisonFilter { +class GreaterThanFilter extends ComparableFilter { protected GreaterThanFilter(String field, Comparable value) { super(field, value); } - @Override - @SuppressWarnings("rawtypes") - protected Set findIndexedIdSet() { - Set idSet = new LinkedHashSet<>(); - if (getIsFieldIndexed()) { - if (getIndexer() instanceof ComparableIndexer && getValue() instanceof Comparable) { - ComparableIndexer comparableIndexer = (ComparableIndexer) getIndexer(); - idSet = comparableIndexer.findGreaterThan(getCollectionName(), getField(), (Comparable) getValue()); - } else { - if (getValue() instanceof Comparable) { - throw new FilterException("gt filter is not supported on indexed field " - + getField()); - } else { - throw new FilterException(getValue() + " is not comparable"); - } - } - } - return idSet; - } - - @Override - protected Set findIdSet(NitriteMap collection) { - throw new FilterException("gt filter cannot be applied on _id field"); - } @Override @SuppressWarnings({"unchecked", "rawtypes"}) @@ -80,4 +56,36 @@ public boolean apply(Pair element) { return false; } + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + public List applyOnIndex(IndexMap indexMap) { + Comparable comparable = getComparable(); + List, Object>> subMap = new ArrayList<>(); + List nitriteIds = new ArrayList<>(); + + Comparable ceilingKey = indexMap.higherKey(comparable); + while (ceilingKey != null) { + // get the starting value, it can be a navigable-map (compound index) + // or list (single field index) + Object value = indexMap.get(ceilingKey); + processIndexValue(value, subMap, nitriteIds); + + ceilingKey = indexMap.higherKey(ceilingKey); + } + + if (!subMap.isEmpty()) { + // if sub-map is populated then filtering on compound index, return sub-map + return subMap; + } else { + // else it is filtering on either single field index, + // or it is a terminal filter on compound index, return only nitrite-ids + return nitriteIds; + } + } + + @Override + public String toString() { + return "(" + getField() + " > " + getValue() + ")"; + } } diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/InFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/InFilter.java index c450e9bee..c4b1b065d 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/InFilter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/InFilter.java @@ -20,21 +20,16 @@ import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.index.ComparableIndexer; -import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.index.IndexMap; import java.util.*; -import static org.dizitart.no2.common.util.ValidationUtils.notNull; - /** * @author Anindya Chatterjee */ -class InFilter extends IndexAwareFilter { +class InFilter extends ComparableArrayFilter { @Getter - private Set> comparableSet; + private final Set> comparableSet; InFilter(String field, Comparable... values) { super(field, values); @@ -42,43 +37,6 @@ class InFilter extends IndexAwareFilter { Collections.addAll(this.comparableSet, values); } - @Override - protected Set findIndexedIdSet() { - validateInFilterValue(getField(), comparableSet); - this.comparableSet = convertValues(this.comparableSet); - - Set idSet = new LinkedHashSet<>(); - if (getIsFieldIndexed()) { - if (getIndexer() instanceof ComparableIndexer && comparableSet != null) { - ComparableIndexer comparableIndexer = (ComparableIndexer) getIndexer(); - idSet = comparableIndexer.findIn(getCollectionName(), getField(), comparableSet); - } else { - if (comparableSet != null && !comparableSet.isEmpty()) { - throw new FilterException("in filter is not supported on indexed field " - + getField()); - } else { - throw new FilterException("invalid in filter"); - } - } - } - return idSet; - } - - @Override - protected Set findIdSet(NitriteMap collection) { - Set idSet = new LinkedHashSet<>(); - if (getOnIdField()) { - for (Comparable comparable : comparableSet) { - if (comparable instanceof String) { - NitriteId nitriteId = NitriteId.createId((String) comparable); - if (collection.containsKey(nitriteId)) { - idSet.add(nitriteId); - } - } - } - } - return idSet; - } @Override public boolean apply(Pair element) { @@ -92,11 +50,28 @@ public boolean apply(Pair element) { return false; } - private void validateInFilterValue(String field, Collection> values) { - notNull(field, "field cannot be null"); - notNull(values, "values cannot be null"); - if (values.size() == 0) { - throw new ValidationException("values cannot be empty"); + public List applyOnIndex(IndexMap indexMap) { + List, Object>> subMap = new ArrayList<>(); + List nitriteIds = new ArrayList<>(); + + for (Pair, ?> entry : indexMap.entries()) { + if (comparableSet.contains(entry.getFirst())) { + processIndexValue(entry.getSecond(), subMap, nitriteIds); + } } + + if (!subMap.isEmpty()) { + // if sub-map is populated then filtering on compound index, return sub-map + return subMap; + } else { + // else it is filtering on either single field index, + // or it is a terminal filter on compound index, return only nitrite-ids + return nitriteIds; + } + } + + @Override + public String toString() { + return "(" + getField() + " in " + Arrays.toString((Comparable[]) getValue()) + ")"; } } diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/IndexAwareFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/IndexAwareFilter.java deleted file mode 100644 index 195291566..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/filters/IndexAwareFilter.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.filters; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.index.Indexer; -import org.dizitart.no2.store.NitriteMap; - -import java.util.Set; - -/** - * @author Anindya Chatterjee - */ -@ToString(exclude = "indexedIdSet") -@EqualsAndHashCode(callSuper = true) -public abstract class IndexAwareFilter extends FieldBasedFilter { - @Getter @Setter - private Boolean isFieldIndexed = false; - - @Getter @Setter - private Boolean onIdField = false; - - @Getter @Setter - private Indexer indexer; - - private Set indexedIdSet; - private Set idSet; - - protected IndexAwareFilter(String field, Object value) { - super(field, value); - } - - protected abstract Set findIndexedIdSet(); - protected abstract Set findIdSet(NitriteMap collection); - - public Set cachedIndexedIds() { - if (indexedIdSet == null || indexedIdSet.isEmpty()) { - indexedIdSet = findIndexedIdSet(); - } - return indexedIdSet; - } - - public Set cachedIds(NitriteMap collection) { - if (idSet == null) { - idSet = findIdSet(collection); - } - return idSet; - } -} diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/IndexOnlyFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/IndexOnlyFilter.java new file mode 100644 index 000000000..5eac4a099 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/filters/IndexOnlyFilter.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.filters; + +/** + * Represents an index-only filter. This filter does not support + * collection scan. + * + * @since 4.0 + * @author Anindya Chatterjee + */ +public abstract class IndexOnlyFilter extends ComparableFilter { + /** + * Instantiates a new {@link IndexOnlyFilter}. + * + * @param field the field + * @param value the value + */ + public IndexOnlyFilter(String field, Object value) { + super(field, value); + } + + public abstract String supportedIndexType(); + + /** + * Checks if other filter can be grouped together with this filter. + * + * @param other the comparable filter + * @return the boolean + */ + public abstract boolean canBeGrouped(IndexOnlyFilter other); +} diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/IndexScanFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/IndexScanFilter.java new file mode 100644 index 000000000..03282e782 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/filters/IndexScanFilter.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.filters; + +import lombok.Getter; +import lombok.ToString; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.exceptions.InvalidOperationException; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Represents a set of filter which can be applied on an index. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +@ToString +public class IndexScanFilter implements Filter { + @Getter + private final List filters; + + /** + * Instantiates a new Index scan filter. + * + * @param filters the filters + */ + public IndexScanFilter(Collection filters) { + this.filters = new ArrayList<>(filters); + } + + @Override + public boolean apply(Pair element) { + throw new InvalidOperationException("index scan filter cannot be applied on collection"); + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/LesserEqualFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/LesserEqualFilter.java index 8c5a98369..0a87b0dbc 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/LesserEqualFilter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/LesserEqualFilter.java @@ -20,47 +20,22 @@ import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.common.tuples.Pair; import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.index.ComparableIndexer; -import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.index.IndexMap; -import java.util.LinkedHashSet; -import java.util.Set; +import java.util.ArrayList; +import java.util.List; +import java.util.NavigableMap; import static org.dizitart.no2.common.util.Numbers.compare; /** * @author Anindya Chatterjee */ -class LesserEqualFilter extends ComparisonFilter { +class LesserEqualFilter extends ComparableFilter { LesserEqualFilter(String field, Comparable value) { super(field, value); } - @Override - @SuppressWarnings("rawtypes") - protected Set findIndexedIdSet() { - Set idSet = new LinkedHashSet<>(); - if (getIsFieldIndexed()) { - if (getIndexer() instanceof ComparableIndexer && getValue() instanceof Comparable) { - ComparableIndexer comparableIndexer = (ComparableIndexer) getIndexer(); - idSet = comparableIndexer.findLesserEqual(getCollectionName(), getField(), (Comparable) getValue()); - } else { - if (getValue() instanceof Comparable) { - throw new FilterException("lte filter is not supported on indexed field " - + getField()); - } else { - throw new FilterException(getValue() + " is not comparable"); - } - } - } - return idSet; - } - - @Override - protected Set findIdSet(NitriteMap collection) { - throw new FilterException("lte filter cannot be applied on _id field"); - } - @Override @SuppressWarnings({"unchecked", "rawtypes"}) public boolean apply(Pair element) { @@ -80,4 +55,36 @@ public boolean apply(Pair element) { return false; } + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + public List applyOnIndex(IndexMap indexMap) { + Comparable comparable = getComparable(); + List, Object>> subMap = new ArrayList<>(); + List nitriteIds = new ArrayList<>(); + + Comparable ceilingKey = indexMap.floorKey(comparable); + while (ceilingKey != null) { + // get the starting value, it can be a navigable-map (compound index) + // or list (single field index) + Object value = indexMap.get(ceilingKey); + processIndexValue(value, subMap, nitriteIds); + + ceilingKey = indexMap.lowerKey(ceilingKey); + } + + if (!subMap.isEmpty()) { + // if sub-map is populated then filtering on compound index, return sub-map + return subMap; + } else { + // else it is filtering on either single field index, + // or it is a terminal filter on compound index, return only nitrite-ids + return nitriteIds; + } + } + + @Override + public String toString() { + return "(" + getField() + " <= " + getValue() + ")"; + } } diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/LesserThanFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/LesserThanFilter.java index d3ad9ec68..e522dbca8 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/LesserThanFilter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/LesserThanFilter.java @@ -20,47 +20,22 @@ import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.common.tuples.Pair; import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.index.ComparableIndexer; -import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.index.IndexMap; -import java.util.LinkedHashSet; -import java.util.Set; +import java.util.ArrayList; +import java.util.List; +import java.util.NavigableMap; import static org.dizitart.no2.common.util.Numbers.compare; /** * @author Anindya Chatterjee */ -class LesserThanFilter extends ComparisonFilter { +class LesserThanFilter extends ComparableFilter { LesserThanFilter(String field, Comparable value) { super(field, value); } - @Override - @SuppressWarnings("rawtypes") - protected Set findIndexedIdSet() { - Set idSet = new LinkedHashSet<>(); - if (getIsFieldIndexed()) { - if (getIndexer() instanceof ComparableIndexer && getValue() instanceof Comparable) { - ComparableIndexer comparableIndexer = (ComparableIndexer) getIndexer(); - idSet = comparableIndexer.findLesserThan(getCollectionName(), getField(), (Comparable) getValue()); - } else { - if (getValue() instanceof Comparable) { - throw new FilterException("lt filter is not supported on indexed field " - + getField()); - } else { - throw new FilterException(getValue() + " is not comparable"); - } - } - } - return idSet; - } - - @Override - protected Set findIdSet(NitriteMap collection) { - throw new FilterException("lt filter cannot be applied on _id field"); - } - @Override @SuppressWarnings({"unchecked", "rawtypes"}) public boolean apply(Pair element) { @@ -80,4 +55,36 @@ public boolean apply(Pair element) { return false; } + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + public List applyOnIndex(IndexMap indexMap) { + Comparable comparable = getComparable(); + List, Object>> subMap = new ArrayList<>(); + List nitriteIds = new ArrayList<>(); + + Comparable ceilingKey = indexMap.lowerKey(comparable); + while (ceilingKey != null) { + // get the starting value, it can be a navigable-map (compound index) + // or list (single field index) + Object value = indexMap.get(ceilingKey); + processIndexValue(value, subMap, nitriteIds); + + ceilingKey = indexMap.lowerKey(ceilingKey); + } + + if (!subMap.isEmpty()) { + // if sub-map is populated then filtering on compound index, return sub-map + return subMap; + } else { + // else it is filtering on either single field index, + // or it is a terminal filter on compound index, return only nitrite-ids + return nitriteIds; + } + } + + @Override + public String toString() { + return "(" + getField() + " < " + getValue() + ")"; + } } diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/LogicalFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/LogicalFilter.java index 4a9fbb722..1ba4abe58 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/LogicalFilter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/LogicalFilter.java @@ -16,11 +16,28 @@ package org.dizitart.no2.filters; +import lombok.Getter; + +import java.util.Arrays; import java.util.List; /** + * Represents a filter which does a logical operation (AND, OR) + * between a set of filters. + * * @author Anindya Chatterjee. + * @since 1.0 */ +@Getter public abstract class LogicalFilter extends NitriteFilter { - public abstract List getFilters(); + private final List filters; + + /** + * Instantiates a new Logical filter. + * + * @param filters the filters + */ + public LogicalFilter(Filter... filters) { + this.filters = Arrays.asList(filters); + } } diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/NitriteFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/NitriteFilter.java index c15e10503..61b97dd7a 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/NitriteFilter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/NitriteFilter.java @@ -20,8 +20,13 @@ import lombok.Setter; import org.dizitart.no2.NitriteConfig; +import java.util.Objects; + /** + * Represents a nitrite filter. + * * @author Anindya Chatterjee. + * @since 4.0 */ @Getter @Setter @@ -29,4 +34,41 @@ public abstract class NitriteFilter implements Filter { private NitriteConfig nitriteConfig; private String collectionName; private Boolean objectFilter = false; + + /** + * Creates an and filter which performs a logical AND operation on two filters and selects + * the documents that satisfy both filters. + *

    + * + * @param filter other filter + * @return the and filter + */ + public Filter and(Filter filter) { + return new AndFilter(this, filter); + } + + /** + * Creates an or filter which performs a logical OR operation on two filters and selects + * the documents that satisfy at least one of the filter. + *

    + * + * @param filter other filter + * @return the or filter + */ + public Filter or(Filter filter) { + return new OrFilter(this, filter); + } + + @Override + public boolean equals(Object o) { + if (o instanceof NitriteFilter) { + return Objects.equals(this.toString(), String.valueOf(o)); + } + return false; + } + + @Override + public int hashCode() { + return toString().hashCode(); + } } diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/NotEqualsFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/NotEqualsFilter.java index d2cd71f8a..daa95d9f8 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/NotEqualsFilter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/NotEqualsFilter.java @@ -1,74 +1,53 @@ package org.dizitart.no2.filters; -import lombok.ToString; import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.index.ComparableIndexer; -import org.dizitart.no2.index.TextIndexer; -import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.index.IndexMap; -import java.util.LinkedHashSet; -import java.util.Set; +import java.util.ArrayList; +import java.util.List; +import java.util.NavigableMap; import static org.dizitart.no2.common.util.ObjectUtils.deepEquals; /** * @author Anindya Chatterjee */ -@ToString -class NotEqualsFilter extends IndexAwareFilter { +class NotEqualsFilter extends ComparableFilter { protected NotEqualsFilter(String field, Object value) { super(field, value); } @Override - @SuppressWarnings("rawtypes") - protected Set findIndexedIdSet() { - Set idSet = new LinkedHashSet<>(); - if (getIsFieldIndexed()) { - if (getValue() == null || getValue() instanceof Comparable) { - if (getIndexer() instanceof ComparableIndexer) { - ComparableIndexer comparableIndexer = (ComparableIndexer) getIndexer(); - idSet = comparableIndexer.findNotEqual(getCollectionName(), getField(), (Comparable) getValue()); - } else if (getIndexer() instanceof TextIndexer && getValue() instanceof String) { - // notEq filter is not compatible with TextIndexer - setIsFieldIndexed(false); - } else { - throw new FilterException("notEq filter is not supported on indexed field " - + getField()); - } - } else { - throw new FilterException(getValue() + " is not comparable"); - } - } - return idSet; + public boolean apply(Pair element) { + Document document = element.getSecond(); + Object fieldValue = document.get(getField()); + return !deepEquals(fieldValue, getValue()); } - @Override - protected Set findIdSet(NitriteMap collection) { - Set idSet = new LinkedHashSet<>(); - if (getOnIdField() && getValue() instanceof String) { - NitriteId nitriteId = NitriteId.createId((String) getValue()); - if (!collection.containsKey(nitriteId)) { - idSet.add(nitriteId); + public List applyOnIndex(IndexMap indexMap) { + List, Object>> subMap = new ArrayList<>(); + List nitriteIds = new ArrayList<>(); + + for (Pair, ?> entry : indexMap.entries()) { + if (!deepEquals(getValue(), entry.getFirst())) { + processIndexValue(entry.getSecond(), subMap, nitriteIds); } } - return idSet; - } - @Override - public boolean apply(Pair element) { - Document document = element.getSecond(); - Object fieldValue = document.get(getField()); - return !deepEquals(fieldValue, getValue()); + if (!subMap.isEmpty()) { + // if sub-map is populated then filtering on compound index, return sub-map + return subMap; + } else { + // else it is filtering on either single field index, + // or it is a terminal filter on compound index, return only nitrite-ids + return nitriteIds; + } } @Override - public void setIsFieldIndexed(Boolean isFieldIndexed) { - if (!(getIndexer() instanceof TextIndexer && getValue() instanceof String)) { - super.setIsFieldIndexed(isFieldIndexed); - } + public String toString() { + return "(" + getField() + " != " + getValue() + ")"; } } diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/NotFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/NotFilter.java index e6562e7d1..b7161322d 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/NotFilter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/NotFilter.java @@ -36,4 +36,9 @@ class NotFilter extends NitriteFilter { public boolean apply(Pair element) { return !filter.apply(element); } + + @Override + public String toString() { + return "(!(" + filter.toString() + "))"; + } } diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/NotInFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/NotInFilter.java index 5cd107c1f..ae2792725 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/NotInFilter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/NotInFilter.java @@ -20,21 +20,16 @@ import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.index.ComparableIndexer; -import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.index.IndexMap; import java.util.*; -import static org.dizitart.no2.common.util.ValidationUtils.notNull; - /** * @author Anindya Chatterjee */ -class NotInFilter extends IndexAwareFilter { +class NotInFilter extends ComparableArrayFilter { @Getter - private Set> comparableSet; + private final Set> comparableSet; NotInFilter(String field, Comparable... values) { super(field, values); @@ -42,49 +37,6 @@ class NotInFilter extends IndexAwareFilter { Collections.addAll(this.comparableSet, values); } - @Override - protected Set findIndexedIdSet() { - validateNotInFilterValue(getField(), comparableSet); - this.comparableSet = convertValues(this.comparableSet); - - Set idSet = new LinkedHashSet<>(); - if (getIsFieldIndexed()) { - if (getIndexer() instanceof ComparableIndexer && comparableSet != null) { - ComparableIndexer comparableIndexer = (ComparableIndexer) getIndexer(); - idSet = comparableIndexer.findNotIn(getCollectionName(), getField(), comparableSet); - } else { - if (comparableSet != null && !comparableSet.isEmpty()) { - throw new FilterException("notIn filter is not supported on indexed field " - + getField()); - } else { - throw new FilterException("invalid notIn filter"); - } - } - } - return idSet; - } - - @Override - protected Set findIdSet(NitriteMap collection) { - Set idSet = new LinkedHashSet<>(); - if (getOnIdField()) { - Set notInSet = new LinkedHashSet<>(); - for (Comparable comparable : comparableSet) { - if (comparable instanceof String) { - NitriteId nitriteId = NitriteId.createId((String) comparable); - notInSet.add(nitriteId); - } - } - - for (NitriteId nitriteId : collection.keySet()) { - if (!notInSet.contains(nitriteId)) { - idSet.add(nitriteId); - } - } - } - return idSet; - } - @Override public boolean apply(Pair element) { Document document = element.getSecond(); @@ -97,11 +49,28 @@ public boolean apply(Pair element) { return true; } - private void validateNotInFilterValue(String field, Collection> values) { - notNull(field, "field cannot be null"); - notNull(values, "values cannot be null"); - if (values.size() == 0) { - throw new ValidationException("values cannot be empty"); + public List applyOnIndex(IndexMap indexMap) { + List, Object>> subMap = new ArrayList<>(); + List nitriteIds = new ArrayList<>(); + + for (Pair, ?> entry : indexMap.entries()) { + if (!comparableSet.contains(entry.getFirst())) { + processIndexValue(entry.getSecond(), subMap, nitriteIds); + } + } + + if (!subMap.isEmpty()) { + // if sub-map is populated then filtering on compound index, return sub-map + return subMap; + } else { + // else it is filtering on either single field index, + // or it is a terminal filter on compound index, return only nitrite-ids + return nitriteIds; } } + + @Override + public String toString() { + return "(" + getField() + " not in " + Arrays.toString((Comparable[]) getValue()) + ")"; + } } diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/OrFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/OrFilter.java index ec53df2d6..7ad22a6e1 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/OrFilter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/OrFilter.java @@ -21,29 +21,45 @@ import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.common.tuples.Pair; -import java.util.Arrays; -import java.util.List; - /** + * Represents an OR filter. + * * @author Anindya Chatterjee + * @since 1.0 */ @Getter public class OrFilter extends LogicalFilter { - private final Filter rhs; - private final Filter lhs; - - OrFilter(Filter lhs, Filter rhs) { - this.lhs = lhs; - this.rhs = rhs; + /** + * Instantiates a new Or filter. + * + * @param filters the filters + */ + OrFilter(Filter... filters) { + super(filters); } @Override - public List getFilters() { - return Arrays.asList(lhs, rhs); + public boolean apply(Pair element) { + boolean result = false; + for (Filter filter : getFilters()) { + result = result || filter.apply(element); + } + return result; } @Override - public boolean apply(Pair element) { - return lhs.apply(element) || rhs.apply(element); + public String toString() { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("("); + for (int i = 0; i < getFilters().size(); i++) { + Filter filter = getFilters().get(i); + if (i == 0) { + stringBuilder.append(filter.toString()); + } else { + stringBuilder.append(" || ").append(filter.toString()); + } + } + stringBuilder.append(")"); + return stringBuilder.toString(); } } diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/RegexFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/RegexFilter.java index 3bb796276..86ea305d1 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/RegexFilter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/RegexFilter.java @@ -52,4 +52,9 @@ public boolean apply(Pair element) { } return false; } + + @Override + public String toString() { + return "(" + getField() + " regex " + getValue() + ")"; + } } diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/StringFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/StringFilter.java index 1e6f8e622..f82c078eb 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/StringFilter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/StringFilter.java @@ -17,13 +17,27 @@ package org.dizitart.no2.filters; /** + * Represents a filter on string values. + * * @author Anindya Chatterjee + * @since 1.0 */ -public abstract class StringFilter extends IndexAwareFilter { +public abstract class StringFilter extends ComparableFilter { + /** + * Instantiates a new String filter. + * + * @param field the field + * @param value the value + */ protected StringFilter(String field, String value) { super(field, value); } + /** + * Gets string value. + * + * @return the string value + */ public String getStringValue() { return (String) getValue(); } diff --git a/nitrite/src/main/java/org/dizitart/no2/filters/TextFilter.java b/nitrite/src/main/java/org/dizitart/no2/filters/TextFilter.java index 2effd4ec8..154e797f7 100644 --- a/nitrite/src/main/java/org/dizitart/no2/filters/TextFilter.java +++ b/nitrite/src/main/java/org/dizitart/no2/filters/TextFilter.java @@ -16,45 +16,188 @@ package org.dizitart.no2.filters; +import lombok.Setter; import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.common.tuples.Pair; import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.index.TextIndexer; +import org.dizitart.no2.index.IndexMap; +import org.dizitart.no2.index.fulltext.TextTokenizer; import org.dizitart.no2.store.NitriteMap; -import java.util.LinkedHashSet; -import java.util.Set; +import java.util.*; + +import static org.dizitart.no2.common.util.StringUtils.stringTokenizer; +import static org.dizitart.no2.common.util.ValidationUtils.notNull; /** + * Represents a nitrite full-text search filter. + * * @author Anindya Chatterjee + * @since 1.0 */ -class TextFilter extends StringFilter { +public class TextFilter extends StringFilter { + @Setter + private TextTokenizer textTokenizer; + + /** + * Instantiates a new Text filter. + * + * @param field the field + * @param value the value + */ TextFilter(String field, String value) { super(field, value); } @Override - protected Set findIndexedIdSet() { - Set idSet = new LinkedHashSet<>(); - if (getIsFieldIndexed()) { - if (getIndexer() instanceof TextIndexer) { - TextIndexer textIndexer = (TextIndexer) getIndexer(); - idSet = textIndexer.findText(getCollectionName(), getField(), getStringValue()); - } else { - throw new FilterException(getField() + " is not full-text indexed"); + public boolean apply(Pair element) { + notNull(getField(), "field cannot be null"); + notNull(getStringValue(), "search term cannot be null"); + String searchString = getStringValue(); + Object docValue = element.getSecond().get(getField()); + + if (!(docValue instanceof String)) { + throw new FilterException("text filter can not be applied on non string field " + getField()); + } + + String docString = (String) docValue; + + if (searchString.startsWith("*") || searchString.endsWith("*")) { + searchString = searchString.replace("*", ""); + } + + return docString.toLowerCase().contains(searchString.toLowerCase()); + } + + @Override + public String toString() { + return "(" + getField() + " like " + getValue() + ")"; + } + + /** + * Apply on index linked hash set. + * + * @param indexMap the index map + * @return the linked hash set + */ + public LinkedHashSet applyOnIndex(NitriteMap> indexMap) { + notNull(getField(), "field cannot be null"); + notNull(getStringValue(), "search term cannot be null"); + String searchString = getStringValue(); + + if (searchString.startsWith("*") || searchString.endsWith("*")) { + return searchByWildCard(indexMap, searchString); + } else { + return searchExactByIndex(indexMap, searchString); + } + } + + @SuppressWarnings("unchecked") + private LinkedHashSet searchExactByIndex(NitriteMap> indexMap, String searchString) { + + Set words = textTokenizer.tokenize(searchString); + Map scoreMap = new HashMap<>(); + for (String word : words) { + List nitriteIds = (List) indexMap.get(word); + if (nitriteIds != null) { + for (NitriteId id : nitriteIds) { + Integer score = scoreMap.get(id); + if (score == null) { + scoreMap.put(id, 1); + } else { + scoreMap.put(id, score + 1); + } + } + } + } + + return sortedIdsByScore(scoreMap); + } + + private LinkedHashSet searchByWildCard(NitriteMap> indexMap, String searchString) { + if (searchString.contentEquals("*")) { + throw new FilterException("* is not a valid search string"); + } + + StringTokenizer stringTokenizer = stringTokenizer(searchString); + if (stringTokenizer.countTokens() > 1) { + throw new FilterException("multiple words with wildcard is not supported"); + } + + if (searchString.startsWith("*") && !searchString.endsWith("*")) { + return searchByLeadingWildCard(indexMap, searchString); + } else if (searchString.endsWith("*") && !searchString.startsWith("*")) { + return searchByTrailingWildCard(indexMap, searchString); + } else { + String term = searchString.substring(1, searchString.length() - 1); + return searchContains(indexMap, term); + } + } + + @SuppressWarnings("unchecked") + private LinkedHashSet searchByLeadingWildCard(NitriteMap> indexMap, String searchString) { + if (searchString.equalsIgnoreCase("*")) { + throw new FilterException("invalid search term '*'"); + } + + LinkedHashSet idSet = new LinkedHashSet<>(); + String term = searchString.substring(1); + + for (Pair> entry : indexMap.entries()) { + String key = entry.getFirst(); + if (key.endsWith(term.toLowerCase())) { + idSet.addAll((List) entry.getSecond()); } } return idSet; } - @Override - protected Set findIdSet(NitriteMap collection) { - throw new FilterException("text filter cannot be applied on _id field"); + @SuppressWarnings("unchecked") + private LinkedHashSet searchByTrailingWildCard(NitriteMap> indexMap, String searchString) { + if (searchString.equalsIgnoreCase("*")) { + throw new FilterException("invalid search term '*'"); + } + + LinkedHashSet idSet = new LinkedHashSet<>(); + String term = searchString.substring(0, searchString.length() - 1); + + for (Pair> entry : indexMap.entries()) { + String key = entry.getFirst(); + if (key.startsWith(term.toLowerCase())) { + idSet.addAll((List) entry.getSecond()); + } + } + return idSet; + } + + @SuppressWarnings("unchecked") + private LinkedHashSet searchContains(NitriteMap> indexMap, String term) { + LinkedHashSet idSet = new LinkedHashSet<>(); + + for (Pair> entry : indexMap.entries()) { + String key = entry.getFirst(); + if (key.contains(term.toLowerCase())) { + idSet.addAll((List) entry.getSecond()); + } + } + return idSet; + } + + private LinkedHashSet sortedIdsByScore(Map unsortedMap) { + List> list = new LinkedList<>(unsortedMap.entrySet()); + Collections.sort(list, (e1, e2) -> (e2.getValue()).compareTo(e1.getValue())); + + LinkedHashSet result = new LinkedHashSet<>(); + for (Map.Entry entry : list) { + result.add(entry.getKey()); + } + + return result; } @Override - public boolean apply(Pair element) { - throw new FilterException(getField() + " is not full-text indexed"); + public List applyOnIndex(IndexMap indexMap) { + return null; } } diff --git a/nitrite/src/main/java/org/dizitart/no2/index/BoundingBox.java b/nitrite/src/main/java/org/dizitart/no2/index/BoundingBox.java index 0414451e7..2d30d8984 100644 --- a/nitrite/src/main/java/org/dizitart/no2/index/BoundingBox.java +++ b/nitrite/src/main/java/org/dizitart/no2/index/BoundingBox.java @@ -19,14 +19,36 @@ import java.io.Serializable; /** + * Represents a bounding box for spatial indexing. + * * @author Anindya Chatterjee */ public interface BoundingBox extends Serializable { + /** + * Gets min x. + * + * @return the min x + */ float getMinX(); + /** + * Gets max x. + * + * @return the max x + */ float getMaxX(); + /** + * Gets min y. + * + * @return the min y + */ float getMinY(); + /** + * Gets max y. + * + * @return the max y + */ float getMaxY(); } diff --git a/nitrite/src/main/java/org/dizitart/no2/index/ComparableIndexer.java b/nitrite/src/main/java/org/dizitart/no2/index/ComparableIndexer.java index 7eb7f3c30..0064753be 100644 --- a/nitrite/src/main/java/org/dizitart/no2/index/ComparableIndexer.java +++ b/nitrite/src/main/java/org/dizitart/no2/index/ComparableIndexer.java @@ -17,304 +17,85 @@ package org.dizitart.no2.index; import org.dizitart.no2.NitriteConfig; -import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.FindPlan; import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.UnknownType; -import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.common.util.Iterables; -import org.dizitart.no2.exceptions.UniqueConstraintException; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.store.NitriteMap; -import org.dizitart.no2.store.NitriteStore; +import org.dizitart.no2.common.FieldValues; +import org.dizitart.no2.common.Fields; -import java.util.Collection; import java.util.LinkedHashSet; -import java.util.Set; -import java.util.concurrent.ConcurrentSkipListSet; - -import static org.dizitart.no2.common.util.ObjectUtils.convertToObjectArray; -import static org.dizitart.no2.common.util.ObjectUtils.deepEquals; -import static org.dizitart.no2.common.util.ValidationUtils.*; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** + * Represents an indexer for {@link Comparable} values. + * * @author Anindya Chatterjee + * @since 4.0 */ -@SuppressWarnings("rawtypes") -public abstract class ComparableIndexer implements Indexer { - private NitriteStore nitriteStore; +public abstract class ComparableIndexer implements NitriteIndexer { + private final Map indexRegistry; - abstract boolean isUnique(); - - public ComparableIndexer clone() throws CloneNotSupportedException { - return (ComparableIndexer) super.clone(); + /** + * Instantiates a new Comparable indexer. + */ + public ComparableIndexer() { + this.indexRegistry = new ConcurrentHashMap<>(); } + /** + * Indicates if it is an unique index. + * + * @return the boolean + */ + abstract boolean isUnique(); + @Override public void initialize(NitriteConfig nitriteConfig) { - this.nitriteStore = nitriteConfig.getNitriteStore(); } @Override - public void writeIndex(NitriteMap collection, NitriteId nitriteId, String field, Object fieldValue) { - validateIndexField(fieldValue, field); - addIndexEntry(collection.getName(), nitriteId, field, fieldValue); + public void validateIndex(Fields fields) { + // nothing to validate } @Override - public void removeIndex(NitriteMap collection, NitriteId nitriteId, String field, Object fieldValue) { - validateIndexField(fieldValue, field); - NitriteMap> indexMap = null; - - if (fieldValue == null) { - indexMap = getIndexMap(collection.getName(), field, UnknownType.class); - removeElementFromIndexMap(indexMap, nitriteId, field, null); - } else if (fieldValue instanceof Comparable) { - indexMap = getIndexMap(collection.getName(), field, fieldValue.getClass()); - removeElementFromIndexMap(indexMap, nitriteId, field, (Comparable) fieldValue); - } else if (fieldValue.getClass().isArray()) { - Object[] array = convertToObjectArray(fieldValue); - - for (Object item : array) { - if (indexMap == null) { - indexMap = getIndexMap(collection.getName(), field, item.getClass()); - } - removeElementFromIndexMap(indexMap, nitriteId, field, (Comparable) item); - } - } else if (fieldValue instanceof Iterable) { - Iterable iterable = (Iterable) fieldValue; - for (Object item : iterable) { - if (indexMap == null) { - indexMap = getIndexMap(collection.getName(), field, item.getClass()); - } - removeElementFromIndexMap(indexMap, nitriteId, field, (Comparable) item); - } - } + public LinkedHashSet findByFilter(FindPlan findPlan, NitriteConfig nitriteConfig) { + NitriteIndex nitriteIndex = findNitriteIndex(findPlan.getIndexDescriptor(), nitriteConfig); + return nitriteIndex.findNitriteIds(findPlan); } @Override - public void updateIndex(NitriteMap collection, NitriteId nitriteId, String field, Object newValue, Object oldValue) { - validateIndexField(newValue, field); - validateIndexField(oldValue, field); - addIndexEntry(collection.getName(), nitriteId, field, newValue); - removeIndex(collection, nitriteId, field, oldValue); + public void writeIndexEntry(FieldValues fieldValues, IndexDescriptor indexDescriptor, + NitriteConfig nitriteConfig) { + NitriteIndex nitriteIndex = findNitriteIndex(indexDescriptor, nitriteConfig); + nitriteIndex.write(fieldValues); } @Override - public void dropIndex(NitriteMap collection, String field) { - // no action required - } - - public Set findEqual(String collectionName, String field, Comparable value) { - NitriteMap> indexMap = - value != null ? getIndexMap(collectionName, field, value.getClass()) - : getIndexMap(collectionName, field, UnknownType.class); - - Set resultSet = null; - if (indexMap != null) { - resultSet = indexMap.get(value); - } - - if (resultSet == null) { - resultSet = new LinkedHashSet<>(); - } - return resultSet; - } - - public Set findNotEqual(String collectionName, String field, Comparable value) { - NitriteMap> indexMap = - value != null ? getIndexMap(collectionName, field, value.getClass()) - : getIndexMap(collectionName, field, UnknownType.class); - - Set resultSet = new LinkedHashSet<>(); - if (indexMap != null) { - for (Pair> entry : indexMap.entries()) { - if (!deepEquals(entry.getFirst(), value)) { - resultSet.addAll(entry.getSecond()); - } - } - } - - return resultSet; - } - - public Set findGreaterThan(String collectionName, String field, Comparable comparable) { - Set resultSet = new LinkedHashSet<>(); - NitriteMap> indexMap = - comparable != null ? getIndexMap(collectionName, field, comparable.getClass()) - : getIndexMap(collectionName, field, UnknownType.class); - - if (indexMap != null) { - Comparable higherKey = indexMap.higherKey(comparable); - while (higherKey != null) { - resultSet.addAll(indexMap.get(higherKey)); - higherKey = indexMap.higherKey(higherKey); - } - } - - return resultSet; - } - - public Set findGreaterEqual(String collectionName, String field, Comparable comparable) { - Set resultSet = new LinkedHashSet<>(); - NitriteMap> indexMap = - comparable != null ? getIndexMap(collectionName, field, comparable.getClass()) - : getIndexMap(collectionName, field, UnknownType.class); - - if (indexMap != null) { - Comparable ceilingKey = indexMap.ceilingKey(comparable); - while (ceilingKey != null) { - resultSet.addAll(indexMap.get(ceilingKey)); - ceilingKey = indexMap.higherKey(ceilingKey); - } - } - - return resultSet; - } - - public Set findLesserThan(String collectionName, String field, Comparable comparable) { - Set resultSet = new LinkedHashSet<>(); - NitriteMap> indexMap = - comparable != null ? getIndexMap(collectionName, field, comparable.getClass()) - : getIndexMap(collectionName, field, UnknownType.class); - - if (indexMap != null) { - Comparable lowerKey = indexMap.lowerKey(comparable); - while (lowerKey != null) { - resultSet.addAll(indexMap.get(lowerKey)); - lowerKey = indexMap.lowerKey(lowerKey); - } - } - - return resultSet; + public void removeIndexEntry(FieldValues fieldValues, IndexDescriptor indexDescriptor, + NitriteConfig nitriteConfig) { + NitriteIndex nitriteIndex = findNitriteIndex(indexDescriptor, nitriteConfig); + nitriteIndex.remove(fieldValues); } - public Set findLesserEqual(String collectionName, String field, Comparable comparable) { - Set resultSet = new LinkedHashSet<>(); - NitriteMap> indexMap = - comparable != null ? getIndexMap(collectionName, field, comparable.getClass()) - : getIndexMap(collectionName, field, UnknownType.class); - - if (indexMap != null) { - Comparable floorKey = indexMap.floorKey(comparable); - while (floorKey != null) { - resultSet.addAll(indexMap.get(floorKey)); - floorKey = indexMap.lowerKey(floorKey); - } - } - - return resultSet; - } - - public Set findIn(String collectionName, String field, Collection> values) { - notNull(values, "values cannot be null"); - notEmpty(values, "values cannot be empty"); - - Set resultSet = new LinkedHashSet<>(); - Class type = Iterables.firstOrNull(values).getClass(); - NitriteMap> indexMap = getIndexMap(collectionName, field, type); - - if (indexMap != null) { - for (Comparable comparable : indexMap.keySet()) { - if (values.contains(comparable)) { - resultSet.addAll(indexMap.get(comparable)); - } - } - } - - return resultSet; + @Override + public void dropIndex(IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig) { + NitriteIndex nitriteIndex = findNitriteIndex(indexDescriptor, nitriteConfig); + nitriteIndex.drop(); } - public Set findNotIn(String collectionName, String field, Collection> values) { - notNull(values, "values cannot be null"); - - Set resultSet = new LinkedHashSet<>(); - Class type = Iterables.firstOrNull(values).getClass(); - NitriteMap> indexMap = getIndexMap(collectionName, field, type); - - if (indexMap != null) { - for (Comparable comparable : indexMap.keySet()) { - if (!values.contains(comparable)) { - resultSet.addAll(indexMap.get(comparable)); - } - } + private NitriteIndex findNitriteIndex(IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig) { + if (indexRegistry.containsKey(indexDescriptor)) { + return indexRegistry.get(indexDescriptor); } - return resultSet; - } - - private void validateIndexField(Object value, String field) { - if (value == null) return; - if (value instanceof Iterable) { - validateIterableIndexField((Iterable) value, field); - } else if (value.getClass().isArray()) { - validateArrayIndexField(value, field); + NitriteIndex nitriteIndex; + if (indexDescriptor.isCompoundIndex()) { + nitriteIndex = new CompoundIndex(indexDescriptor, nitriteConfig.getNitriteStore()); } else { - if (!(value instanceof Comparable)) { - throw new ValidationException(value + " is not comparable"); - } + nitriteIndex = new SingleFieldIndex(indexDescriptor, nitriteConfig.getNitriteStore()); } - } - - private void addIndexEntry(String collectionName, NitriteId id, String field, Object element) { - NitriteMap> indexMap - = getIndexMap(collectionName, field, UnknownType.class); - - if (element == null) { - addElementToIndexMap(indexMap, id, field, null); - } else if (element instanceof Comparable) { - addElementToIndexMap(indexMap, id, field, (Comparable) element); - } else if (element.getClass().isArray()) { - Object[] array = convertToObjectArray(element); - for (Object item : array) { - addElementToIndexMap(indexMap, id, field, (Comparable) item); - } - } else if (element instanceof Iterable) { - Iterable iterable = (Iterable) element; - for (Object item : iterable) { - addElementToIndexMap(indexMap, id, field, (Comparable) item); - } - } - } - - private void addElementToIndexMap(NitriteMap> indexMap, - NitriteId id, String field, Comparable element) { - // create the nitriteId list associated with the value - ConcurrentSkipListSet nitriteIdList - = indexMap.get(element); - - if (nitriteIdList == null) { - nitriteIdList = new ConcurrentSkipListSet<>(); - } - - if (isUnique() && nitriteIdList.size() == 1 - && !nitriteIdList.contains(id)) { - // if key is already exists for unique type, throw error - throw new UniqueConstraintException("unique key constraint violation for " + field); - } - - nitriteIdList.add(id); - indexMap.put(element, nitriteIdList); - } - - private void removeElementFromIndexMap(NitriteMap> indexMap, - NitriteId nitriteId, String field, Comparable element) { - // create the nitrite list associated with the value - ConcurrentSkipListSet nitriteIdList = indexMap.get(element); - if (nitriteIdList != null && !nitriteIdList.isEmpty()) { - nitriteIdList.remove(nitriteId); - if (nitriteIdList.size() == 0) { - indexMap.remove(element); - } else { - indexMap.put(element, nitriteIdList); - } - } - } - - @SuppressWarnings("rawtypes") - private NitriteMap> getIndexMap( - String collectionName, String field, Class keyType) { - - String mapName = getIndexMapName(collectionName, field); - return nitriteStore.openMap(mapName, keyType, ConcurrentSkipListSet.class); + indexRegistry.put(indexDescriptor, nitriteIndex); + return nitriteIndex; } } diff --git a/nitrite/src/main/java/org/dizitart/no2/index/CompoundIndex.java b/nitrite/src/main/java/org/dizitart/no2/index/CompoundIndex.java new file mode 100644 index 000000000..beec17621 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/index/CompoundIndex.java @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.index; + +import lombok.Getter; +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.DBNull; +import org.dizitart.no2.common.FieldValues; +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.filters.ComparableFilter; +import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.store.NitriteStore; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.NavigableMap; +import java.util.concurrent.ConcurrentSkipListMap; + +import static org.dizitart.no2.common.util.IndexUtils.deriveIndexMapName; +import static org.dizitart.no2.common.util.ObjectUtils.convertToObjectArray; + +/** + * Represents a nitrite compound index. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +public class CompoundIndex implements NitriteIndex { + @Getter + private final IndexDescriptor indexDescriptor; + private final NitriteStore nitriteStore; + + /** + * Instantiates a new Compound index. + * + * @param indexDescriptor the index descriptor + * @param nitriteStore the nitrite store + */ + public CompoundIndex(IndexDescriptor indexDescriptor, NitriteStore nitriteStore) { + this.indexDescriptor = indexDescriptor; + this.nitriteStore = nitriteStore; + } + + public void write(FieldValues fieldValues) { + Fields fields = fieldValues.getFields(); + List fieldNames = fields.getFieldNames(); + + String firstField = fieldNames.get(0); + Object firstValue = fieldValues.get(firstField); + + // NOTE: only first field can have array or iterable value, subsequent fields can not + validateIndexField(firstValue, firstField); + + NitriteMap> indexMap = findIndexMap(); + if (firstValue == null) { + addIndexElement(indexMap, fieldValues, DBNull.getInstance()); + } else if (firstValue instanceof Comparable) { + //wrap around a db value + DBValue dbValue = new DBValue((Comparable) firstValue); + addIndexElement(indexMap, fieldValues, dbValue); + } else if (firstValue.getClass().isArray()) { + Object[] array = convertToObjectArray(firstValue); + + for (Object item : array) { + // wrap around db value + DBValue dbValue = item == null ? DBNull.getInstance() : new DBValue((Comparable) item); + addIndexElement(indexMap, fieldValues, dbValue); + } + } else if (firstValue instanceof Iterable) { + Iterable iterable = (Iterable) firstValue; + + for (Object item : iterable) { + // wrap around db value + DBValue dbValue = item != null ? new DBValue((Comparable) item) : DBNull.getInstance(); + addIndexElement(indexMap, fieldValues, dbValue); + } + } + } + + @Override + public void remove(FieldValues fieldValues) { + Fields fields = fieldValues.getFields(); + List fieldNames = fields.getFieldNames(); + + String firstField = fieldNames.get(0); + Object firstValue = fieldValues.get(firstField); + + // NOTE: only first field can have array or iterable value, subsequent fields can not + validateIndexField(firstValue, firstField); + NitriteMap> indexMap = findIndexMap(); + + if (firstValue == null) { + removeIndexElement(indexMap, fieldValues, DBNull.getInstance()); + } else if (firstValue instanceof Comparable) { + // wrap around db value + DBValue dbValue = new DBValue((Comparable) firstValue); + removeIndexElement(indexMap, fieldValues, dbValue); + } else if (firstValue.getClass().isArray()) { + Object[] array = convertToObjectArray(firstValue); + + for (Object item : array) { + // wrap around db value + DBValue dbValue = item == null ? DBNull.getInstance() : new DBValue((Comparable) item); + removeIndexElement(indexMap, fieldValues, dbValue); + } + } else if (firstValue instanceof Iterable) { + Iterable iterable = (Iterable) firstValue; + + for (Object item : iterable) { + // wrap around db value + DBValue dbValue = item != null ? new DBValue((Comparable) item) : DBNull.getInstance(); + removeIndexElement(indexMap, fieldValues, dbValue); + } + } + } + + @Override + public void drop() { + NitriteMap> indexMap = findIndexMap(); + indexMap.clear(); + indexMap.drop(); + } + + @Override + public LinkedHashSet findNitriteIds(FindPlan findPlan) { + if (findPlan.getIndexScanFilter() == null) return new LinkedHashSet<>(); + + NitriteMap> indexMap = findIndexMap(); + return scanIndex(findPlan, indexMap); + } + + private void addIndexElement(NitriteMap> indexMap, + FieldValues fieldValues, DBValue element) { + NavigableMap subMap = indexMap.get(element); + if (subMap == null) { + // index are always in ascending order + subMap = new ConcurrentSkipListMap<>(); + } + + populateSubMap(subMap, fieldValues, 1); + indexMap.put(element, subMap); + } + + private void removeIndexElement(NitriteMap> indexMap, + FieldValues fieldValues, DBValue element) { + NavigableMap subMap = indexMap.get(element); + if (subMap != null && !subMap.isEmpty()) { + deleteFromSubMap(subMap, fieldValues, 1); + indexMap.put(element, subMap); + } + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + private void populateSubMap(NavigableMap subMap, FieldValues fieldValues, int startIndex) { + if (startIndex >= fieldValues.getValues().size()) return; + + Pair pair = fieldValues.getValues().get(startIndex); + Object value = pair.getSecond(); + DBValue dbValue; + if (value == null) { + dbValue = DBNull.getInstance(); + } else { + if (Iterable.class.isAssignableFrom(value.getClass()) || value.getClass().isArray()) { + throw new IndexingException("compound multikey index is supported on the first field of the index only"); + } + + if (!(value instanceof Comparable)) { + throw new IndexingException(value + " is not comparable"); + } + dbValue = new DBValue((Comparable) value); + } + + if (startIndex == fieldValues.getValues().size() - 1) { + // terminal field + List nitriteIds = (List) subMap.get(dbValue); + nitriteIds = addNitriteIds(nitriteIds, fieldValues); + subMap.put(dbValue, nitriteIds); + } else { + // intermediate fields + NavigableMap subMap2 = (NavigableMap) subMap.get(dbValue); + if (subMap2 == null) { + // index are always in ascending order + subMap2 = new ConcurrentSkipListMap<>(); + } + + subMap.put(dbValue, subMap2); + populateSubMap(subMap2, fieldValues, startIndex + 1); + } + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + private void deleteFromSubMap(NavigableMap subMap, FieldValues fieldValues, int startIndex) { + Pair pair = fieldValues.getValues().get(startIndex); + Object value = pair.getSecond(); + DBValue dbValue; + if (value == null) { + dbValue = DBNull.getInstance(); + } else { + if (!(value instanceof Comparable)) { + return; + } + dbValue = new DBValue((Comparable) value); + } + + if (startIndex == fieldValues.getValues().size() - 1) { + // terminal field + List nitriteIds = (List) subMap.get(dbValue); + nitriteIds = removeNitriteIds(nitriteIds, fieldValues); + if (nitriteIds == null || nitriteIds.isEmpty()) { + subMap.remove(dbValue); + } else { + subMap.put(dbValue, nitriteIds); + } + } else { + // intermediate fields + NavigableMap subMap2 = (NavigableMap) subMap.get(dbValue); + if (subMap2 == null) { + return; + } + + deleteFromSubMap(subMap2, fieldValues, startIndex + 1); + subMap.put(dbValue, subMap2); + } + } + + private NitriteMap> findIndexMap() { + String mapName = deriveIndexMapName(indexDescriptor); + return nitriteStore.openMap(mapName, DBValue.class, ConcurrentSkipListMap.class); + } + + private LinkedHashSet scanIndex(FindPlan findPlan, + NitriteMap> indexMap) { + List filters = findPlan.getIndexScanFilter().getFilters(); + IndexMap iMap = new IndexMap(indexMap); + IndexScanner indexScanner = new IndexScanner(iMap); + return indexScanner.doScan(filters, findPlan.getIndexScanOrder()); + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/index/DBValue.java b/nitrite/src/main/java/org/dizitart/no2/index/DBValue.java new file mode 100644 index 000000000..161b488ce --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/index/DBValue.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.index; + +import lombok.AccessLevel; +import lombok.Data; +import lombok.Setter; +import org.dizitart.no2.common.util.Comparables; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +/** + * @author Anindya Chatterjee + */ +@Data +public class DBValue implements Comparable, Serializable { + private static final long serialVersionUID = 1617440702L; + + @Setter(AccessLevel.PRIVATE) + private Comparable value; + + public DBValue(Comparable value) { + this.value = value; + } + + @Override + public int compareTo(DBValue o) { + if (o == null || o.value == null) { + return 1; + } + + if (value == null) { + return -1; + } + + return Comparables.compare(value, o.value); + } + + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.writeObject(value); + } + + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + this.value = (Comparable) stream.readObject(); + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/index/IndexDescriptor.java b/nitrite/src/main/java/org/dizitart/no2/index/IndexDescriptor.java new file mode 100644 index 000000000..12bf72253 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/index/IndexDescriptor.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2017-2020. Nitrite author or authors. + * + * Licensed 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.dizitart.no2.index; + +import lombok.AccessLevel; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.dizitart.no2.common.Fields; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +import static org.dizitart.no2.common.util.ValidationUtils.notEmpty; +import static org.dizitart.no2.common.util.ValidationUtils.notNull; + +/** + * Represents a nitrite database index. + * + * @author Anindya Chatterjee + * @since 1.0 + */ +@Data +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class IndexDescriptor implements Comparable, Serializable { + private static final long serialVersionUID = 1576690829L; + + /** + * Specifies the type of the index. + * + * @return the type of the index. + * @see IndexType + */ + @Getter + private String indexType; + + /** + * Gets the target fields for the index. + * + * @return the target fields. + */ + @Getter + private Fields indexFields; + + /** + * Gets the collection name. + * + * @return the collection name. + */ + @Getter + private String collectionName; + + /** + * Instantiates a new Index. + * + * @param indexType the index type + * @param fields the value + * @param collectionName the collection name + */ + public IndexDescriptor(String indexType, Fields fields, String collectionName) { + notNull(indexType, "indexType cannot be null"); + notNull(fields, "fields cannot be null"); + notNull(collectionName, "collectionName cannot be null"); + notEmpty(collectionName, "collectionName cannot be empty"); + + this.indexType = indexType; + this.indexFields = fields; + this.collectionName = collectionName; + } + + @Override + public int compareTo(IndexDescriptor other) { + if (other == null) return 1; + + // compound index have highest cardinality + if (this.isCompoundIndex() && !other.isCompoundIndex()) return 1; + + // unique index has the next highest cardinality + if (this.isUniqueIndex() && !other.isUniqueIndex()) return 1; + + // for two unique indices, the one with encompassing higher + // number of fields has the higher cardinality + if (this.isUniqueIndex()) { + return this.indexFields.compareTo(other.indexFields); + } + + // for two non-unique indices, the one with encompassing higher + // number of fields has the higher cardinality + if (!other.isUniqueIndex()) { + return this.indexFields.compareTo(other.indexFields); + } + + return -1; + } + + public boolean isCompoundIndex() { + return indexFields.getFieldNames().size() > 1; + } + + private boolean isUniqueIndex() { + return indexType.equals(IndexType.UNIQUE); + } + + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.writeUTF(indexType); + stream.writeObject(indexFields); + stream.writeUTF(collectionName); + } + + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + indexType = stream.readUTF(); + indexFields = (Fields) stream.readObject(); + collectionName = stream.readUTF(); + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/index/IndexEntry.java b/nitrite/src/main/java/org/dizitart/no2/index/IndexEntry.java deleted file mode 100644 index 99ee89858..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/index/IndexEntry.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.index; - -import lombok.*; -import org.dizitart.no2.collection.NitriteCollection; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; - -import static org.dizitart.no2.common.util.ValidationUtils.notEmpty; -import static org.dizitart.no2.common.util.ValidationUtils.notNull; - -/** - * Represents a nitrite database index. - * - * @author Anindya Chatterjee - * @see NitriteCollection#createIndex(String, IndexOptions) - * @since 1.0 - */ -@ToString -@EqualsAndHashCode -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class IndexEntry implements Comparable, Serializable { - private static final long serialVersionUID = 1576690829L; - - /** - * Specifies the type of the index. - * - * @return the type of the index. - * @see IndexType - */ - @Getter - private String indexType; - - /** - * Gets the target field for the index. - * - * @return the target field. - */ - @Getter - private String field; - - /** - * Gets the collection name. - * - * @return the collection name. - */ - @Getter - private String collectionName; - - /** - * Instantiates a new Index. - * - * @param indexType the index type - * @param field the value - * @param collectionName the collection name - */ - public IndexEntry(String indexType, String field, String collectionName) { - notNull(indexType, "indexType cannot be null"); - notNull(field, "field cannot be null"); - notNull(collectionName, "collectionName cannot be null"); - notEmpty(collectionName, "collectionName cannot be empty"); - - this.indexType = indexType; - this.field = field; - this.collectionName = collectionName; - } - - @Override - public int compareTo(IndexEntry other) { - String string = collectionName + field + indexType; - String otherString = other.collectionName + other.field + other.indexType; - return string.compareTo(otherString); - } - - private void writeObject(ObjectOutputStream stream) throws IOException { - stream.writeUTF(indexType); - stream.writeUTF(field); - stream.writeUTF(collectionName); - } - - private void readObject(ObjectInputStream stream) throws IOException { - indexType = stream.readUTF(); - field = stream.readUTF(); - collectionName = stream.readUTF(); - } -} diff --git a/nitrite/src/main/java/org/dizitart/no2/index/IndexMap.java b/nitrite/src/main/java/org/dizitart/no2/index/IndexMap.java new file mode 100644 index 000000000..458c4b337 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/index/IndexMap.java @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.index; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.DBNull; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.store.NitriteMap; + +import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * Represents an index map. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +@SuppressWarnings("unchecked") +public class IndexMap { + private NitriteMap nitriteMap; + private NavigableMap navigableMap; + + @Getter + @Setter + private boolean reverseScan; + + /** + * Instantiates a new {@link IndexMap}. + * + * @param nitriteMap the nitrite map + */ + public IndexMap(NitriteMap nitriteMap) { + this.nitriteMap = nitriteMap; + } + + /** + * Instantiates a new {@link IndexMap}. + * + * @param navigableMap the navigable map + */ + public IndexMap(NavigableMap navigableMap) { + this.navigableMap = navigableMap; + } + + /** + * Get the largest key that is smaller than the given key, or null if no + * such key exists. + * + * @param the type parameter + * @param key the key + * @return the t + */ + public > T lowerKey(T key) { + DBValue dbKey = key == null ? DBNull.getInstance() : new DBValue(key); + if (!reverseScan) { + if (nitriteMap != null) { + dbKey = nitriteMap.lowerKey(dbKey); + } else if (navigableMap != null) { + dbKey = navigableMap.lowerKey(dbKey); + } + } else { + if (nitriteMap != null) { + dbKey = nitriteMap.higherKey(dbKey); + } else if (navigableMap != null) { + dbKey = navigableMap.higherKey(dbKey); + } + } + + return dbKey == null || dbKey instanceof DBNull ? null : (T) dbKey.getValue(); + } + + /** + * Get the smallest key that is larger than the given key, or null if no + * such key exists. + * + * @param the type parameter + * @param key the key + * @return the t + */ + public > T higherKey(T key) { + DBValue dbKey = key == null ? DBNull.getInstance() : new DBValue(key); + if (!reverseScan) { + if (nitriteMap != null) { + dbKey = nitriteMap.higherKey(dbKey); + } else if (navigableMap != null) { + dbKey = navigableMap.higherKey(dbKey); + } + } else { + if (nitriteMap != null) { + dbKey = nitriteMap.lowerKey(dbKey); + } else if (navigableMap != null) { + dbKey = navigableMap.lowerKey(dbKey); + } + } + + return dbKey == null || dbKey instanceof DBNull ? null : (T) dbKey.getValue(); + } + + /** + * Get the smallest key that is larger or equal to this key. + * + * @param the type parameter + * @param key the key + * @return the t + */ + public > T ceilingKey(T key) { + DBValue dbKey = key == null ? DBNull.getInstance() : new DBValue(key); + if (!reverseScan) { + if (nitriteMap != null) { + dbKey = nitriteMap.ceilingKey(dbKey); + } else if (navigableMap != null) { + dbKey = navigableMap.ceilingKey(dbKey); + } + } else { + if (nitriteMap != null) { + dbKey = nitriteMap.floorKey(dbKey); + } else if (navigableMap != null) { + dbKey = navigableMap.floorKey(dbKey); + } + } + + return dbKey == null || dbKey instanceof DBNull ? null : (T) dbKey.getValue(); + } + + /** + * Get the largest key that is smaller or equal to this key. + * + * @param the type parameter + * @param key the key + * @return the t + */ + public > T floorKey(T key) { + DBValue dbKey = key == null ? DBNull.getInstance() : new DBValue(key); + if (!reverseScan) { + if (nitriteMap != null) { + dbKey = nitriteMap.floorKey(dbKey); + } else if (navigableMap != null) { + dbKey = navigableMap.floorKey(dbKey); + } + } else { + if (nitriteMap != null) { + dbKey = nitriteMap.ceilingKey(dbKey); + } else if (navigableMap != null) { + dbKey = navigableMap.ceilingKey(dbKey); + } + } + + return dbKey == null || dbKey instanceof DBNull ? null : (T) dbKey.getValue(); + } + + /** + * Gets the value mapped with the specified key or null otherwise. + * + * @param comparable the comparable + * @return the object + */ + public Object get(Comparable comparable) { + DBValue dbKey = comparable == null ? DBNull.getInstance() : new DBValue(comparable); + if (nitriteMap != null) { + return nitriteMap.get(dbKey); + } else if (navigableMap != null) { + return navigableMap.get(dbKey); + } + return null; + } + + /** + * Returns the iterable entries of the indexed items. + * + * @return the iterable + */ + public Iterable, ?>> entries() { + if (nitriteMap != null) { + Iterator> entryIterator; + if (!reverseScan) { + entryIterator = nitriteMap.entries().iterator(); + } else { + entryIterator = nitriteMap.reversedEntries().iterator(); + } + + return (Iterable, ?>>) () -> new Iterator, ?>>() { + @Override + public boolean hasNext() { + return entryIterator.hasNext(); + } + + @Override + public Pair, ?> next() { + Pair next = entryIterator.next(); + DBValue dbKey = next.getFirst(); + if (dbKey instanceof DBNull) { + return new Pair<>(null, next.getSecond()); + } else { + return new Pair<>(dbKey.getValue(), next.getSecond()); + } + } + }; + } else if (navigableMap != null) { + Iterator> entryIterator; + if (reverseScan) { + entryIterator = navigableMap.descendingMap().entrySet().iterator(); + } else { + entryIterator = navigableMap.entrySet().iterator(); + } + + return (Iterable, ?>>) () -> new Iterator, ?>>() { + @Override + public boolean hasNext() { + return entryIterator.hasNext(); + } + + @Override + public Pair, ?> next() { + Map.Entry next = entryIterator.next(); + DBValue dbKey = next.getKey(); + if (dbKey instanceof DBNull) { + return new Pair<>(null, next.getValue()); + } else { + return new Pair<>(dbKey.getValue(), next.getValue()); + } + } + }; + } + return null; + } + + /** + * Gets the terminal nitrite ids from this map. + * + * @return the terminal nitrite ids + */ + public List getTerminalNitriteIds() { + List terminalResult = new CopyOnWriteArrayList<>(); + + // scan each entry of the navigable map and collect all terminal nitrite-ids + for (Pair, ?> entry : entries()) { + // if the value is terminal, collect all nitrite-ids + if (entry.getSecond() instanceof List) { + List nitriteIds = (List) entry.getSecond(); + terminalResult.addAll(nitriteIds); + } + + // if the value is not terminal, scan recursively + if (entry.getSecond() instanceof NavigableMap) { + NavigableMap subMap = (NavigableMap) entry.getSecond(); + IndexMap indexMap = new IndexMap(subMap); + List nitriteIds = indexMap.getTerminalNitriteIds(); + terminalResult.addAll(nitriteIds); + } + } + + return terminalResult; + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/index/IndexMeta.java b/nitrite/src/main/java/org/dizitart/no2/index/IndexMeta.java index cb04a58ae..9729eccfa 100644 --- a/nitrite/src/main/java/org/dizitart/no2/index/IndexMeta.java +++ b/nitrite/src/main/java/org/dizitart/no2/index/IndexMeta.java @@ -36,18 +36,18 @@ public class IndexMeta implements Serializable { private static final long serialVersionUID = 1576690663L; - private IndexEntry indexEntry; + private IndexDescriptor indexDescriptor; private String indexMap; private AtomicBoolean isDirty; private void writeObject(ObjectOutputStream stream) throws IOException { - stream.writeObject(indexEntry); + stream.writeObject(indexDescriptor); stream.writeUTF(indexMap); stream.writeObject(isDirty); } private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { - indexEntry = (IndexEntry) stream.readObject(); + indexDescriptor = (IndexDescriptor) stream.readObject(); indexMap = stream.readUTF(); isDirty = (AtomicBoolean) stream.readObject(); } diff --git a/nitrite/src/main/java/org/dizitart/no2/index/IndexOptions.java b/nitrite/src/main/java/org/dizitart/no2/index/IndexOptions.java index a0201c0d5..75bf1d6b6 100644 --- a/nitrite/src/main/java/org/dizitart/no2/index/IndexOptions.java +++ b/nitrite/src/main/java/org/dizitart/no2/index/IndexOptions.java @@ -19,13 +19,11 @@ import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; -import org.dizitart.no2.collection.NitriteCollection; /** * Represents options to apply while creating an index. * * @author Anindya Chatterjee - * @see NitriteCollection#createIndex(String, IndexOptions) * @since 1.0 */ @EqualsAndHashCode @@ -41,20 +39,6 @@ public class IndexOptions { @Setter private String indexType; - /** - * Indicates whether an index to be created in a non-blocking - * way. - * - * @param async if set to `true` then the index will be created asynchronously; - * otherwise create index operation will wait until all existing - * documents are indexed. - * @return `true` if index is to be created asynchronously; otherwise `false`. - * @see NitriteCollection#createIndex(String, IndexOptions) - */ - @Getter - @Setter - private boolean async = false; - /** * Creates an {@link IndexOptions} with the specified `indexType`. Index creation * will be synchronous with this option. @@ -63,21 +47,8 @@ public class IndexOptions { * @return a new synchronous index creation option. */ public static IndexOptions indexOptions(String indexType) { - return indexOptions(indexType, false); - } - - /** - * Creates an {@link IndexOptions} with the specified `indexType` and `async` flag. - * - * @param indexType the type of index to be created. - * @param async if set to `true` then the index would be created asynchronously; - * otherwise synchronously. - * @return a new index creation option. - */ - public static IndexOptions indexOptions(String indexType, boolean async) { IndexOptions options = new IndexOptions(); options.setIndexType(indexType); - options.setAsync(async); return options; } } diff --git a/nitrite/src/main/java/org/dizitart/no2/index/IndexScanner.java b/nitrite/src/main/java/org/dizitart/no2/index/IndexScanner.java new file mode 100644 index 000000000..0236b8395 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/index/IndexScanner.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.index; + +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.filters.ComparableFilter; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.NavigableMap; + +/** + * Represents an {@link IndexMap} scanner. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +public class IndexScanner { + private final IndexMap indexMap; + + /** + * Instantiates a new {@link IndexScanner}. + * + * @param indexMap the index map + */ + public IndexScanner(IndexMap indexMap) { + this.indexMap = indexMap; + } + + /** + * Scans the {@link IndexMap} and returns the {@link NitriteId}s of the matching elements. + * + * @param filters the filters + * @param indexScanOrder the index scan order + * @return the linked hash set + */ + @SuppressWarnings("unchecked") + public LinkedHashSet doScan(List filters, Map indexScanOrder) { + // linked-hash-set to return only unique ids preserving the order in index + LinkedHashSet nitriteIds = new LinkedHashSet<>(); + + if (filters != null && !filters.isEmpty()) { + // get the first filter to start scanning + ComparableFilter comparableFilter = filters.get(0); + + if (comparableFilter != null) { + // set the scan order of the index map + boolean reverseScan = (indexScanOrder != null + && indexScanOrder.containsKey(comparableFilter.getField())) + ? indexScanOrder.get(comparableFilter.getField()) + : false; + indexMap.setReverseScan(reverseScan); + + // apply the filter on the index map + // result can be list of nitrite ids or list of navigable maps + List scanResult = comparableFilter.applyOnIndex(indexMap); + if (isEmptyList(scanResult)) { + // if list is empty then no need for further scanning + return nitriteIds; + } else if (isNitriteIdList(scanResult)) { + // if this is a list of nitrite ids then add those to the + // result and no further scanning is required as we have + // reached the terminal nitrite ids + List idList = (List) scanResult; + nitriteIds.addAll(idList); + } else if (isNavigableMapList(scanResult)) { + // if this is a list of sub maps, then take each of the sub map + // and the next filter and scan the sub map + List> subMaps = (List>) scanResult; + List remainingFilter = filters.subList(1, filters.size()); + + for (NavigableMap subMap : subMaps) { + // create an index map from the sub map and scan to get the + // terminal nitrite ids + IndexMap indexMap = new IndexMap(subMap); + IndexScanner subMapScanner = new IndexScanner(indexMap); + LinkedHashSet subResult = subMapScanner.doScan(remainingFilter, indexScanOrder); + nitriteIds.addAll(subResult); + } + } + } else { + // filter is not comparable filter, so index scanning can not continue + throw new FilterException("index scan is not supported for " + comparableFilter.getClass().getName()); + } + } else { + // if no more filter is left, get all terminal nitrite ids from + // index map and return them in the order. + List terminalResult = indexMap.getTerminalNitriteIds(); + nitriteIds.addAll(terminalResult); + } + + return nitriteIds; + } + + private boolean isEmptyList(List list) { + return list == null || list.isEmpty(); + } + + private boolean isNitriteIdList(List list) { + Object value = list.get(0); + return value instanceof NitriteId; + } + + private boolean isNavigableMapList(List list) { + Object value = list.get(0); + return value instanceof NavigableMap; + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/index/IndexType.java b/nitrite/src/main/java/org/dizitart/no2/index/IndexType.java index bd6431854..efbafec64 100644 --- a/nitrite/src/main/java/org/dizitart/no2/index/IndexType.java +++ b/nitrite/src/main/java/org/dizitart/no2/index/IndexType.java @@ -17,10 +17,24 @@ package org.dizitart.no2.index; /** + * Represents a type of nitrite index. + * * @author Anindya Chatterjee + * @since 4.0 */ public interface IndexType { - String Unique = "Unique"; - String NonUnique = "NonUnique"; - String Fulltext = "Fulltext"; + /** + * A unique index. + */ + String UNIQUE = "Unique"; + + /** + * A non-unique index. + */ + String NON_UNIQUE = "NonUnique"; + + /** + * A nitrite full-text index. + */ + String FULL_TEXT = "Fulltext"; } diff --git a/nitrite/src/main/java/org/dizitart/no2/index/Indexer.java b/nitrite/src/main/java/org/dizitart/no2/index/Indexer.java deleted file mode 100644 index 1ced8e8f3..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/index/Indexer.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.index; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.module.NitritePlugin; -import org.dizitart.no2.store.NitriteMap; - -import static org.dizitart.no2.common.Constants.INDEX_PREFIX; -import static org.dizitart.no2.common.Constants.INTERNAL_NAME_SEPARATOR; - -/** - * @author Anindya Chatterjee. - */ -public interface Indexer extends NitritePlugin, Cloneable { - String getIndexType(); - - void writeIndex(NitriteMap collection, NitriteId nitriteId, String field, Object fieldValue); - - void removeIndex(NitriteMap collection, NitriteId nitriteId, String field, Object fieldValue); - - void updateIndex(NitriteMap collection, NitriteId nitriteId, String field, Object newValue, Object oldValue); - - void dropIndex(NitriteMap collection, String field); - - Indexer clone() throws CloneNotSupportedException; - - default String getIndexMapName(String collectionName, String field) { - return INDEX_PREFIX + - INTERNAL_NAME_SEPARATOR + - collectionName + - INTERNAL_NAME_SEPARATOR + - field + - INTERNAL_NAME_SEPARATOR + - getIndexType(); - } -} diff --git a/nitrite/src/main/java/org/dizitart/no2/index/NitriteIndex.java b/nitrite/src/main/java/org/dizitart/no2/index/NitriteIndex.java new file mode 100644 index 000000000..8881058e2 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/index/NitriteIndex.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.index; + +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.FieldValues; +import org.dizitart.no2.exceptions.UniqueConstraintException; +import org.dizitart.no2.exceptions.ValidationException; + +import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; + +import static org.dizitart.no2.common.util.ValidationUtils.validateArrayIndexField; +import static org.dizitart.no2.common.util.ValidationUtils.validateIterableIndexField; + +/** + * Represents a nitrite index. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +public interface NitriteIndex { + /** + * Gets index descriptor. + * + * @return the index descriptor + */ + IndexDescriptor getIndexDescriptor(); + + /** + * Writes a {@link FieldValues} in the index. + * + * @param fieldValues the field values + */ + void write(FieldValues fieldValues); + + /** + * Removes a {@link FieldValues} from the index. + * + * @param fieldValues the field values + */ + void remove(FieldValues fieldValues); + + /** + * Drops this index. + */ + void drop(); + + /** + * Finds a set of {@link NitriteId}s from the index after executing the {@link FindPlan}. + * + * @param findPlan the find plan + * @return the linked hash set + */ + LinkedHashSet findNitriteIds(FindPlan findPlan); + + /** + * Indicates if this is an unique index. + * + * @return the boolean + */ + default boolean isUnique() { + return getIndexDescriptor().getIndexType().equalsIgnoreCase(IndexType.UNIQUE); + } + + /** + * Validates the index field. + * + * @param value the value + * @param field the field + */ + default void validateIndexField(Object value, String field) { + if (value == null) return; + if (value instanceof Iterable) { + validateIterableIndexField((Iterable) value, field); + } else if (value.getClass().isArray()) { + validateArrayIndexField(value, field); + } else { + if (!(value instanceof Comparable)) { + throw new ValidationException(value + " is not comparable"); + } + } + } + + /** + * Adds a {@link NitriteId} of the {@link FieldValues} to the existing indexed list of {@link NitriteId}s. + * + * @param nitriteIds the nitrite ids + * @param fieldValues the field values + * @return the list + */ + default List addNitriteIds(List nitriteIds, FieldValues fieldValues) { + if (nitriteIds == null) { + nitriteIds = new CopyOnWriteArrayList<>(); + } + + if (isUnique() && nitriteIds.size() == 1 + && !nitriteIds.contains(fieldValues.getNitriteId())) { + // if key is already exists for unique type, throw error + throw new UniqueConstraintException("unique key constraint violation for " + fieldValues.getFields()); + } + + // index always are in ascending format + nitriteIds.add(fieldValues.getNitriteId()); + return nitriteIds; + } + + /** + * Removes a {@link NitriteId} of the {@link FieldValues} from the existing indexed list of {@link NitriteId}s. + * + * @param nitriteIds the nitrite ids + * @param fieldValues the field values + * @return the list + */ + default List removeNitriteIds(List nitriteIds, FieldValues fieldValues) { + if (nitriteIds != null && !nitriteIds.isEmpty()) { + nitriteIds.remove(fieldValues.getNitriteId()); + } + return nitriteIds; + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/index/NitriteIndexer.java b/nitrite/src/main/java/org/dizitart/no2/index/NitriteIndexer.java new file mode 100644 index 000000000..850aed466 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/index/NitriteIndexer.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2017-2020. Nitrite author or authors. + * + * Licensed 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.dizitart.no2.index; + +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.FieldValues; +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.common.module.NitritePlugin; + +import java.util.LinkedHashSet; + +/** + * Represents an indexer for creating a nitrite index. + * + * @author Anindya Chatterjee. + * @since 4.0 + */ +public interface NitriteIndexer extends NitritePlugin { + /** + * Gets the index type. + * + * @return the index type + */ + String getIndexType(); + + /** + * Validates an index on the fields. + * + * @param fields the fields + */ + void validateIndex(Fields fields); + + /** + * Drops the index specified by the index descriptor. + * + * @param indexDescriptor the index descriptor + * @param nitriteConfig the nitrite config + */ + void dropIndex(IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig); + + /** + * Writes an index entry. + * + * @param fieldValues the field values + * @param indexDescriptor the index descriptor + * @param nitriteConfig the nitrite config + */ + void writeIndexEntry(FieldValues fieldValues, IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig); + + /** + * Removes an index entry. + * + * @param fieldValues the field values + * @param indexDescriptor the index descriptor + * @param nitriteConfig the nitrite config + */ + void removeIndexEntry(FieldValues fieldValues, IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig); + + /** + * Finds a list of {@link NitriteId} after executing the {@link FindPlan} on the index. + * + * @param findPlan the find plan + * @param nitriteConfig the nitrite config + * @return the linked hash set + */ + LinkedHashSet findByFilter(FindPlan findPlan, NitriteConfig nitriteConfig); +} diff --git a/nitrite/src/main/java/org/dizitart/no2/index/NitriteTextIndexer.java b/nitrite/src/main/java/org/dizitart/no2/index/NitriteTextIndexer.java index a73574964..47cd4cf96 100644 --- a/nitrite/src/main/java/org/dizitart/no2/index/NitriteTextIndexer.java +++ b/nitrite/src/main/java/org/dizitart/no2/index/NitriteTextIndexer.java @@ -17,292 +17,93 @@ package org.dizitart.no2.index; import org.dizitart.no2.NitriteConfig; -import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.FindPlan; import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.common.FieldValues; +import org.dizitart.no2.common.Fields; import org.dizitart.no2.exceptions.IndexingException; import org.dizitart.no2.index.fulltext.EnglishTextTokenizer; import org.dizitart.no2.index.fulltext.TextTokenizer; -import org.dizitart.no2.store.IndexCatalog; -import org.dizitart.no2.store.NitriteMap; -import org.dizitart.no2.store.NitriteStore; -import java.io.IOException; -import java.util.*; -import java.util.concurrent.ConcurrentSkipListSet; - -import static org.dizitart.no2.common.util.ObjectUtils.convertToObjectArray; -import static org.dizitart.no2.common.util.StringUtils.stringTokenizer; -import static org.dizitart.no2.common.util.ValidationUtils.*; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** + * Represents a nitrite text indexer. + * * @author Anindya Chatterjee + * @since 4.0 */ -@SuppressWarnings("rawtypes") -public class NitriteTextIndexer implements TextIndexer { +public class NitriteTextIndexer implements NitriteIndexer { private final TextTokenizer textTokenizer; - private IndexCatalog indexCatalog; - private NitriteStore nitriteStore; + private final Map indexRegistry; + /** + * Instantiates a new {@link NitriteTextIndexer}. + */ public NitriteTextIndexer() { this.textTokenizer = new EnglishTextTokenizer(); + this.indexRegistry = new ConcurrentHashMap<>(); } + /** + * Instantiates a new {@link NitriteTextIndexer}. + * + * @param textTokenizer the text tokenizer + */ public NitriteTextIndexer(TextTokenizer textTokenizer) { this.textTokenizer = textTokenizer; + this.indexRegistry = new ConcurrentHashMap<>(); } - public NitriteTextIndexer clone() throws CloneNotSupportedException { - return (NitriteTextIndexer) super.clone(); + @Override + public void initialize(NitriteConfig nitriteConfig) { } @Override public String getIndexType() { - return IndexType.Fulltext; + return IndexType.FULL_TEXT; } @Override - public Set findText(String collectionName, String field, String searchString) { - notNull(field, "field cannot be null"); - notNull(searchString, "search term cannot be null"); - - try { - if (searchString.startsWith("*") || searchString.endsWith("*")) { - return searchByWildCard(collectionName, field, searchString); - } else { - return searchExactByIndex(collectionName, field, searchString); - } - } catch (IOException ioe) { - throw new IndexingException("could not search on full-text index", ioe); + public void validateIndex(Fields fields) { + if (fields.getFieldNames().size() > 1) { + throw new IndexingException("text index can only be created on a single field"); } } @Override - public void writeIndex(NitriteMap collection, NitriteId nitriteId, String field, Object fieldValue) { - createOrUpdate(collection, nitriteId, field, fieldValue); + public void dropIndex(IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig) { + TextIndex textIndex = findTextIndex(indexDescriptor, nitriteConfig); + textIndex.drop(); } @Override - @SuppressWarnings("unchecked") - public void removeIndex(NitriteMap collection, NitriteId nitriteId, String field, Object fieldValue) { - try { - validateStringValue(fieldValue, field); - Set words = decompose(fieldValue); - - NitriteMap indexMap - = getIndexMap(collection.getName(), field); - - for (String word : words) { - ConcurrentSkipListSet nitriteIds = (ConcurrentSkipListSet) indexMap.get(word); - if (nitriteIds != null) { - nitriteIds.remove(nitriteId); - - if (nitriteIds.isEmpty()) { - indexMap.remove(word); - } else { - indexMap.put(word, nitriteIds); - } - } - } - } catch (IOException ioe) { - throw new IndexingException("failed to remove full-text index data for " + field + " with id " + nitriteId); - } - } - - @Override - public void updateIndex(NitriteMap collection, NitriteId nitriteId, String field, Object newValue, Object oldValue) { - removeIndex(collection, nitriteId, field, oldValue); - createOrUpdate(collection, nitriteId, field, newValue); + public void writeIndexEntry(FieldValues fieldValues, IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig) { + TextIndex textIndex = findTextIndex(indexDescriptor, nitriteConfig); + textIndex.write(fieldValues); } @Override - public void dropIndex(NitriteMap collection, String field) { - indexCatalog.dropIndexEntry(collection.getName(), field); + public void removeIndexEntry(FieldValues fieldValues, IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig) { + TextIndex textIndex = findTextIndex(indexDescriptor, nitriteConfig); + textIndex.remove(fieldValues); } @Override - public void initialize(NitriteConfig nitriteConfig) { - this.nitriteStore = nitriteConfig.getNitriteStore(); - this.indexCatalog = this.nitriteStore.getIndexCatalog(); - } - - @SuppressWarnings("rawtypes") - private NitriteMap getIndexMap(String collectionName, String field) { - String mapName = getIndexMapName(collectionName, field); - return nitriteStore.openMap(mapName, String.class, ConcurrentSkipListSet.class); - } - - private void validateStringValue(Object value, String field) { - if (value == null || value instanceof String) return; - - if (value instanceof Iterable) { - validateStringIterableIndexField((Iterable) value, field); - } else if (value.getClass().isArray()) { - validateStringArrayIndexField(value, field); - } else { - throw new IndexingException("string data is expected"); - } - } - - @SuppressWarnings("unchecked") - private void createOrUpdate(NitriteMap collection, NitriteId id, String field, Object fieldValue) { - try { - validateStringValue(fieldValue, field); - Set words = decompose(fieldValue); - - NitriteMap indexMap - = getIndexMap(collection.getName(), field); - - for (String word : words) { - ConcurrentSkipListSet nitriteIds = (ConcurrentSkipListSet) indexMap.get(word); - - if (nitriteIds == null) { - nitriteIds = new ConcurrentSkipListSet<>(); - } - nitriteIds.add(id); - indexMap.put(word, nitriteIds); - } - } catch (IOException ioe) { - throw new IndexingException("could not write full-text index data for " + fieldValue, ioe); - } - } - - private Set decompose(Object fieldValue) throws IOException { - Set result = new HashSet<>(); - if (fieldValue == null) { - result.add(null); - } else if (fieldValue instanceof String) { - result.add((String) fieldValue); - } else if (fieldValue instanceof Iterable) { - Iterable iterable = (Iterable) fieldValue; - for (Object item : iterable) { - result.addAll(decompose(item)); - } - } else if (fieldValue.getClass().isArray()) { - Object[] array = convertToObjectArray(fieldValue); - for (Object item : array) { - result.addAll(decompose(item)); - } - } - - Set words = new HashSet<>(); - for (String item : result) { - words.addAll(textTokenizer.tokenize(item)); - } - - return words; - } - - private Set searchByWildCard(String collectionName, String field, String searchString) { - if (searchString.contentEquals("*")) { - throw new FilterException("* is not a valid search string"); - } - - StringTokenizer stringTokenizer = stringTokenizer(searchString); - if (stringTokenizer.countTokens() > 1) { - throw new FilterException("multiple words with wildcard is not supported"); - } - - if (searchString.startsWith("*") && !searchString.endsWith("*")) { - return searchByLeadingWildCard(collectionName, field, searchString); - } else if (searchString.endsWith("*") && !searchString.startsWith("*")) { - return searchByTrailingWildCard(collectionName, field, searchString); - } else { - String term = searchString.substring(1, searchString.length() - 1); - return searchContains(collectionName, field, term); - } - } - - @SuppressWarnings("unchecked") - private Set searchByTrailingWildCard(String collectionName, String field, String searchString) { - if (searchString.equalsIgnoreCase("*")) { - throw new FilterException("invalid search term '*'"); - } - - NitriteMap indexMap - = getIndexMap(collectionName, field); - Set idSet = new LinkedHashSet<>(); - String term = searchString.substring(0, searchString.length() - 1); - - for (Pair entry : indexMap.entries()) { - String key = (String) entry.getFirst(); - if (key.startsWith(term.toLowerCase())) { - idSet.addAll((ConcurrentSkipListSet) entry.getSecond()); - } - } - return idSet; - } - - @SuppressWarnings("unchecked") - private Set searchContains(String collectionName, String field, String term) { - NitriteMap indexMap - = getIndexMap(collectionName, field); - Set idSet = new LinkedHashSet<>(); - - for (Pair entry : indexMap.entries()) { - String key = (String) entry.getFirst(); - if (key.contains(term.toLowerCase())) { - idSet.addAll((ConcurrentSkipListSet) entry.getSecond()); - } - } - return idSet; + public LinkedHashSet findByFilter(FindPlan findPlan, NitriteConfig nitriteConfig) { + TextIndex textIndex = findTextIndex(findPlan.getIndexDescriptor(), nitriteConfig); + return textIndex.findNitriteIds(findPlan); } - @SuppressWarnings("unchecked") - private Set searchByLeadingWildCard(String collectionName, String field, String searchString) { - if (searchString.equalsIgnoreCase("*")) { - throw new FilterException("invalid search term '*'"); - } - - NitriteMap indexMap - = getIndexMap(collectionName, field); - Set idSet = new LinkedHashSet<>(); - String term = searchString.substring(1); - - for (Pair entry : indexMap.entries()) { - String key = (String) entry.getFirst(); - if (key.endsWith(term.toLowerCase())) { - idSet.addAll((ConcurrentSkipListSet) entry.getSecond()); - } - } - return idSet; - } - - @SuppressWarnings("unchecked") - private Set searchExactByIndex(String collectionName, String field, String searchString) throws IOException { - NitriteMap indexMap - = getIndexMap(collectionName, field); - - Set words = textTokenizer.tokenize(searchString); - Map scoreMap = new HashMap<>(); - for (String word : words) { - ConcurrentSkipListSet nitriteIds = (ConcurrentSkipListSet) indexMap.get(word); - if (nitriteIds != null) { - for (NitriteId id : nitriteIds) { - Integer score = scoreMap.get(id); - if (score == null) { - scoreMap.put(id, 1); - } else { - scoreMap.put(id, score + 1); - } - } - } - } - - Map sortedScoreMap = sortByScore(scoreMap); - return sortedScoreMap.keySet(); - } - - private > Map sortByScore(Map unsortedMap) { - List> list = new LinkedList<>(unsortedMap.entrySet()); - Collections.sort(list, (e1, e2) -> (e2.getValue()).compareTo(e1.getValue())); - - Map result = new LinkedHashMap<>(); - for (Map.Entry entry : list) { - result.put(entry.getKey(), entry.getValue()); + private TextIndex findTextIndex(IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig) { + if (indexRegistry.containsKey(indexDescriptor)) { + return indexRegistry.get(indexDescriptor); } - return result; + TextIndex textIndex = new TextIndex(textTokenizer, indexDescriptor, nitriteConfig.getNitriteStore()); + indexRegistry.put(indexDescriptor, textIndex); + return textIndex; } } diff --git a/nitrite/src/main/java/org/dizitart/no2/index/NonUniqueIndexer.java b/nitrite/src/main/java/org/dizitart/no2/index/NonUniqueIndexer.java index d4d171dd6..9d3c8b6d0 100644 --- a/nitrite/src/main/java/org/dizitart/no2/index/NonUniqueIndexer.java +++ b/nitrite/src/main/java/org/dizitart/no2/index/NonUniqueIndexer.java @@ -17,7 +17,10 @@ package org.dizitart.no2.index; /** + * Represents a non unique indexer. + * * @author Anindya Chatterjee + * @since 4.0 */ public final class NonUniqueIndexer extends ComparableIndexer { @@ -28,6 +31,6 @@ boolean isUnique() { @Override public String getIndexType() { - return IndexType.NonUnique; + return IndexType.NON_UNIQUE; } } diff --git a/nitrite/src/main/java/org/dizitart/no2/index/SingleFieldIndex.java b/nitrite/src/main/java/org/dizitart/no2/index/SingleFieldIndex.java new file mode 100644 index 000000000..592caad86 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/index/SingleFieldIndex.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.index; + +import lombok.Getter; +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.DBNull; +import org.dizitart.no2.common.FieldValues; +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.filters.ComparableFilter; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.store.NitriteStore; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import static org.dizitart.no2.common.util.IndexUtils.deriveIndexMapName; +import static org.dizitart.no2.common.util.ObjectUtils.convertToObjectArray; + +/** + * Represents a nitrite index on a single field. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +public class SingleFieldIndex implements NitriteIndex { + @Getter + private final IndexDescriptor indexDescriptor; + private final NitriteStore nitriteStore; + + /** + * Instantiates a new {@link SingleFieldIndex}. + * + * @param indexDescriptor the index descriptor + * @param nitriteStore the nitrite store + */ + public SingleFieldIndex(IndexDescriptor indexDescriptor, NitriteStore nitriteStore) { + this.indexDescriptor = indexDescriptor; + this.nitriteStore = nitriteStore; + } + + @Override + public void write(FieldValues fieldValues) { + Fields fields = fieldValues.getFields(); + List fieldNames = fields.getFieldNames(); + + String firstField = fieldNames.get(0); + Object element = fieldValues.get(firstField); + + NitriteMap> indexMap = findIndexMap(); + + if (element == null) { + addIndexElement(indexMap, fieldValues, DBNull.getInstance()); + } else if (element instanceof Comparable) { + // wrap around db value + DBValue dbValue = new DBValue((Comparable) element); + addIndexElement(indexMap, fieldValues, dbValue); + } else if (element.getClass().isArray()) { + Object[] array = convertToObjectArray(element); + + for (Object item : array) { + // wrap around db value + DBValue dbValue = item == null ? DBNull.getInstance() : new DBValue((Comparable) item); + addIndexElement(indexMap, fieldValues, dbValue); + } + } else if (element instanceof Iterable) { + Iterable iterable = (Iterable) element; + + for (Object item : iterable) { + // wrap around db value + DBValue dbValue = item == null ? DBNull.getInstance() : new DBValue((Comparable) item); + addIndexElement(indexMap, fieldValues, dbValue); + } + } + } + + @Override + public void remove(FieldValues fieldValues) { + Fields fields = fieldValues.getFields(); + List fieldNames = fields.getFieldNames(); + + String firstField = fieldNames.get(0); + Object element = fieldValues.get(firstField); + + NitriteMap> indexMap = findIndexMap(); + if (element == null) { + removeIndexElement(indexMap, fieldValues, DBNull.getInstance()); + } else if (element instanceof Comparable) { + // wrap around db value + DBValue dbValue = new DBValue((Comparable) element); + removeIndexElement(indexMap, fieldValues, dbValue); + } else if (element.getClass().isArray()) { + Object[] array = convertToObjectArray(element); + + for (Object item : array) { + // wrap around db value + DBValue dbValue = item == null ? DBNull.getInstance() : new DBValue((Comparable) item); + removeIndexElement(indexMap, fieldValues, dbValue); + } + } else if (element instanceof Iterable) { + Iterable iterable = (Iterable) element; + + for (Object item : iterable) { + // wrap around db value + DBValue dbValue = item == null ? DBNull.getInstance() : new DBValue((Comparable) item); + removeIndexElement(indexMap, fieldValues, dbValue); + } + } + } + + @Override + public void drop() { + NitriteMap> indexMap = findIndexMap(); + indexMap.clear(); + indexMap.drop(); + } + + @Override + public LinkedHashSet findNitriteIds(FindPlan findPlan) { + if (findPlan.getIndexScanFilter() == null) return new LinkedHashSet<>(); + + NitriteMap> indexMap = findIndexMap(); + return scanIndex(findPlan, indexMap); + } + + @SuppressWarnings("unchecked") + private void addIndexElement(NitriteMap> indexMap, + FieldValues fieldValues, DBValue element) { + List nitriteIds = (List) indexMap.get(element); + nitriteIds = addNitriteIds(nitriteIds, fieldValues); + indexMap.put(element, nitriteIds); + } + + @SuppressWarnings("unchecked") + private void removeIndexElement(NitriteMap> indexMap, + FieldValues fieldValues, DBValue element) { + List nitriteIds = (List) indexMap.get(element); + if (nitriteIds != null && !nitriteIds.isEmpty()) { + nitriteIds.remove(fieldValues.getNitriteId()); + if (nitriteIds.size() == 0) { + indexMap.remove(element); + } else { + indexMap.put(element, nitriteIds); + } + } + } + + private NitriteMap> findIndexMap() { + String mapName = deriveIndexMapName(indexDescriptor); + return nitriteStore.openMap(mapName, DBValue.class, CopyOnWriteArrayList.class); + } + + private LinkedHashSet scanIndex(FindPlan findPlan, + NitriteMap> indexMap) { + List filters = findPlan.getIndexScanFilter().getFilters(); + IndexMap iMap = new IndexMap(indexMap); + IndexScanner indexScanner = new IndexScanner(iMap); + return indexScanner.doScan(filters, findPlan.getIndexScanOrder()); + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/index/TextIndex.java b/nitrite/src/main/java/org/dizitart/no2/index/TextIndex.java new file mode 100644 index 000000000..3c6a4aba4 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/index/TextIndex.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.index; + +import lombok.Getter; +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.FieldValues; +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.filters.ComparableFilter; +import org.dizitart.no2.filters.TextFilter; +import org.dizitart.no2.index.fulltext.TextTokenizer; +import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.store.NitriteStore; + +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; + +import static org.dizitart.no2.common.util.IndexUtils.deriveIndexMapName; +import static org.dizitart.no2.common.util.ObjectUtils.convertToObjectArray; +import static org.dizitart.no2.common.util.ValidationUtils.validateStringArrayIndexField; +import static org.dizitart.no2.common.util.ValidationUtils.validateStringIterableIndexField; + +/** + * Represents a nitrite full-text index. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +public class TextIndex implements NitriteIndex { + @Getter + private final IndexDescriptor indexDescriptor; + private final NitriteStore nitriteStore; + private final TextTokenizer textTokenizer; + + /** + * Instantiates a new {@link TextIndex}. + * + * @param textTokenizer the text tokenizer + * @param indexDescriptor the index descriptor + * @param nitriteStore the nitrite store + */ + public TextIndex(TextTokenizer textTokenizer, + IndexDescriptor indexDescriptor, + NitriteStore nitriteStore) { + this.textTokenizer = textTokenizer; + this.indexDescriptor = indexDescriptor; + this.nitriteStore = nitriteStore; + } + + @Override + public void write(FieldValues fieldValues) { + Fields fields = fieldValues.getFields(); + List fieldNames = fields.getFieldNames(); + + String firstField = fieldNames.get(0); + Object element = fieldValues.get(firstField); + + NitriteMap> indexMap = findIndexMap(); + + if (element == null) { + addIndexElement(indexMap, fieldValues, null); + } else if (element instanceof String) { + addIndexElement(indexMap, fieldValues, (String) element); + } else if (element.getClass().isArray()) { + validateStringArrayIndexField(element, firstField); + Object[] array = convertToObjectArray(element); + + for (Object item : array) { + addIndexElement(indexMap, fieldValues, (String) item); + } + } else if (element instanceof Iterable) { + validateStringIterableIndexField((Iterable) element, firstField); + Iterable iterable = (Iterable) element; + + for (Object item : iterable) { + addIndexElement(indexMap, fieldValues, (String) item); + } + } else { + throw new IndexingException("string data is expected"); + } + } + + @Override + public void remove(FieldValues fieldValues) { + Fields fields = fieldValues.getFields(); + List fieldNames = fields.getFieldNames(); + + String firstField = fieldNames.get(0); + Object element = fieldValues.get(firstField); + + NitriteMap> indexMap = findIndexMap(); + if (element == null) { + removeIndexElement(indexMap, fieldValues, null); + } else if (element instanceof String) { + removeIndexElement(indexMap, fieldValues, (String) element); + } else if (element.getClass().isArray()) { + validateStringArrayIndexField(element, firstField); + Object[] array = convertToObjectArray(element); + + for (Object item : array) { + removeIndexElement(indexMap, fieldValues, (String) item); + } + } else if (element instanceof Iterable) { + validateStringIterableIndexField((Iterable) element, firstField); + Iterable iterable = (Iterable) element; + + for (Object item : iterable) { + removeIndexElement(indexMap, fieldValues, (String) item); + } + } else { + throw new IndexingException("string data is expected"); + } + } + + @Override + public void drop() { + NitriteMap> indexMap = findIndexMap(); + indexMap.clear(); + indexMap.drop(); + } + + @Override + public LinkedHashSet findNitriteIds(FindPlan findPlan) { + if (findPlan.getIndexScanFilter() == null) return new LinkedHashSet<>(); + + NitriteMap> indexMap = findIndexMap(); + List filters = findPlan.getIndexScanFilter().getFilters(); + + if (filters.size() == 1 && filters.get(0) instanceof TextFilter) { + TextFilter textFilter = (TextFilter) filters.get(0); + textFilter.setTextTokenizer(textTokenizer); + return textFilter.applyOnIndex(indexMap); + } + throw new FilterException("invalid filter found for full-text index"); + } + + private NitriteMap> findIndexMap() { + String mapName = deriveIndexMapName(indexDescriptor); + return nitriteStore.openMap(mapName, String.class, CopyOnWriteArrayList.class); + } + + @SuppressWarnings("unchecked") + private void addIndexElement(NitriteMap> indexMap, FieldValues fieldValues, String value) { + Set words = decompose(value); + + for (String word : words) { + List nitriteIds = (List) indexMap.get(word); + + if (nitriteIds == null) { + nitriteIds = new CopyOnWriteArrayList<>(); + } + + nitriteIds = addNitriteIds(nitriteIds, fieldValues); + indexMap.put(word, nitriteIds); + } + } + + @SuppressWarnings("unchecked") + private void removeIndexElement(NitriteMap> indexMap, FieldValues fieldValues, String value) { + Set words = decompose(value); + for (String word : words) { + List nitriteIds = (List) indexMap.get(word); + if (nitriteIds != null && !nitriteIds.isEmpty()) { + nitriteIds.remove(fieldValues.getNitriteId()); + if (nitriteIds.isEmpty()) { + indexMap.remove(word); + } else { + indexMap.put(word, nitriteIds); + } + } + } + } + + private Set decompose(Object fieldValue) { + Set result = new HashSet<>(); + if (fieldValue == null) { + result.add(null); + } else if (fieldValue instanceof String) { + result.add((String) fieldValue); + } else if (fieldValue instanceof Iterable) { + Iterable iterable = (Iterable) fieldValue; + for (Object item : iterable) { + result.addAll(decompose(item)); + } + } else if (fieldValue.getClass().isArray()) { + Object[] array = convertToObjectArray(fieldValue); + for (Object item : array) { + result.addAll(decompose(item)); + } + } + + Set words = new HashSet<>(); + for (String item : result) { + words.addAll(textTokenizer.tokenize(item)); + } + + return words; + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/index/TextIndexer.java b/nitrite/src/main/java/org/dizitart/no2/index/TextIndexer.java deleted file mode 100644 index 0c11c7713..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/index/TextIndexer.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.index; - -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.filters.FluentFilter; - -import java.util.Set; - -/** - * Represents a full-text indexing engine. It scans a document - * and modifies full-text index entries by decomposing texts of - * an indexed field, into a set of string tokens. It uses the - * full-text index to search for a specific text. - * - * @author Anindya Chatterjee - * @see FluentFilter#text(String) - * @since 1.0 - */ -public interface TextIndexer extends Indexer { - /** - * Finds matching text using full-text index. - * - * @param collectionName collection name - * @param field the value - * @param value the value - * @return the result set - */ - Set findText(String collectionName, String field, String value); -} diff --git a/nitrite/src/main/java/org/dizitart/no2/index/UniqueIndexer.java b/nitrite/src/main/java/org/dizitart/no2/index/UniqueIndexer.java index 6d3d3e9b1..2eb859694 100644 --- a/nitrite/src/main/java/org/dizitart/no2/index/UniqueIndexer.java +++ b/nitrite/src/main/java/org/dizitart/no2/index/UniqueIndexer.java @@ -17,12 +17,15 @@ package org.dizitart.no2.index; /** + * Represents a nitrite unique indexer. + * * @author Anindya Chatterjee. + * @since 4.0 */ public final class UniqueIndexer extends ComparableIndexer { @Override public String getIndexType() { - return IndexType.Unique; + return IndexType.UNIQUE; } @Override diff --git a/nitrite/src/main/java/org/dizitart/no2/index/fulltext/TextTokenizer.java b/nitrite/src/main/java/org/dizitart/no2/index/fulltext/TextTokenizer.java index 3610d2cc4..5b7876d5f 100644 --- a/nitrite/src/main/java/org/dizitart/no2/index/fulltext/TextTokenizer.java +++ b/nitrite/src/main/java/org/dizitart/no2/index/fulltext/TextTokenizer.java @@ -16,16 +16,12 @@ package org.dizitart.no2.index.fulltext; -import org.dizitart.no2.index.TextIndexer; - -import java.io.IOException; import java.util.Set; /** * A stop-word based string tokenizer. * * @author Anindya Chatterjee. - * @see TextIndexer * @see EnglishTextTokenizer * @since 1.0 */ @@ -43,9 +39,8 @@ public interface TextTokenizer { * * @param text the text to tokenize * @return the set of tokens. - * @throws IOException if a low-level I/O error occurs. */ - Set tokenize(String text) throws IOException; + Set tokenize(String text); /** * Gets all stop-words for a language. diff --git a/nitrite/src/main/java/org/dizitart/no2/mapper/NitriteMapper.java b/nitrite/src/main/java/org/dizitart/no2/mapper/NitriteMapper.java deleted file mode 100644 index 2a2864c43..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/mapper/NitriteMapper.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapper; - -import org.dizitart.no2.module.NitritePlugin; - -/** - * @author Anindya Chatterjee. - */ -public interface NitriteMapper extends NitritePlugin { - Target convert(Source source, Class type); - - boolean isValueType(Class type); - - boolean isValue(Object object); -} diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/CollectionInstruction.java b/nitrite/src/main/java/org/dizitart/no2/migration/CollectionInstruction.java index fbbe24056..edc12009c 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/CollectionInstruction.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/CollectionInstruction.java @@ -1,12 +1,22 @@ package org.dizitart.no2.migration; +import org.dizitart.no2.common.Fields; import org.dizitart.no2.common.tuples.Pair; import org.dizitart.no2.common.tuples.Triplet; /** + * Represents a migration instruction set for {@link org.dizitart.no2.collection.NitriteCollection}. + * * @author Anindya Chatterjee + * @since 4.0 */ -public interface CollectionInstruction extends Composable { +public interface CollectionInstruction extends Instruction { + /** + * Adds an instruction to rename a {@link org.dizitart.no2.collection.NitriteCollection}. + * + * @param name the name + * @return the instruction + */ default CollectionInstruction rename(String name) { MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.CollectionRename); @@ -27,10 +37,25 @@ public void addStep(MigrationStep step) { }; } + /** + * Adds an instruction to add new field to the documents of + * a {@link org.dizitart.no2.collection.NitriteCollection}. + * + * @param fieldName the field name + * @return the collection instruction + */ default CollectionInstruction addField(String fieldName) { return addField(fieldName, null); } + /** + * Adds an instruction to add new field with a default value, into the documents of + * a {@link org.dizitart.no2.collection.NitriteCollection}. + * + * @param fieldName the field name + * @param defaultValue the default value + * @return the collection instruction + */ default CollectionInstruction addField(String fieldName, Object defaultValue) { MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.CollectionAddField); @@ -39,6 +64,14 @@ default CollectionInstruction addField(String fieldName, Object defaultValue) { return this; } + /** + * Adds an instruction to add new field with value generator, into the document of + * a {@link org.dizitart.no2.collection.NitriteCollection}. + * + * @param fieldName the field name + * @param generator the generator + * @return the collection instruction + */ default CollectionInstruction addField(String fieldName, Generator generator) { MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.CollectionAddField); @@ -47,6 +80,14 @@ default CollectionInstruction addField(String fieldName, Generator generator) return this; } + /** + * Adds an instruction to rename a field to the document of + * a {@link org.dizitart.no2.collection.NitriteCollection}. + * + * @param oldName the old name + * @param newName the new name + * @return the collection instruction + */ default CollectionInstruction renameField(String oldName, String newName) { MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.CollectionRenameField); @@ -55,6 +96,13 @@ default CollectionInstruction renameField(String oldName, String newName) { return this; } + /** + * Adds an instruction to delete a field from the document of + * a {@link org.dizitart.no2.collection.NitriteCollection}. + * + * @param fieldName the field name + * @return the collection instruction + */ default CollectionInstruction deleteField(String fieldName) { MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.CollectionDeleteField); @@ -63,14 +111,26 @@ default CollectionInstruction deleteField(String fieldName) { return this; } - default CollectionInstruction dropIndex(String indexedFieldName) { + /** + * Adds an instruction to drop an index from a {@link org.dizitart.no2.collection.NitriteCollection}. + * + * @param indexedFieldNames the indexed field names + * @return the collection instruction + */ + default CollectionInstruction dropIndex(String... indexedFieldNames) { + Fields indexedFields = Fields.withNames(indexedFieldNames); MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.CollectionDropIndex); - migrationStep.setArguments(new Pair<>(collectionName(), indexedFieldName)); + migrationStep.setArguments(new Pair<>(collectionName(), indexedFields)); addStep(migrationStep); return this; } + /** + * Adds an instruction to drop all indices from a {@link org.dizitart.no2.collection.NitriteCollection}. + * + * @return the collection instruction + */ default CollectionInstruction dropAllIndices() { MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.CollectionDropIndices); @@ -79,13 +139,26 @@ default CollectionInstruction dropAllIndices() { return this; } - default CollectionInstruction createIndex(String fieldName, String indexType) { + /** + * Adds an instruction to create an index in a {@link org.dizitart.no2.collection.NitriteCollection}. + * + * @param fieldNames the field names + * @param indexType the index type + * @return the collection instruction + */ + default CollectionInstruction createIndex(String indexType, String... fieldNames) { + Fields indexedFields = Fields.withNames(fieldNames); MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.CollectionCreateIndex); - migrationStep.setArguments(new Triplet<>(collectionName(), fieldName, indexType)); + migrationStep.setArguments(new Triplet<>(collectionName(), indexedFields, indexType)); addStep(migrationStep); return this; } + /** + * The name of the collection for this instruction. + * + * @return the name + */ String collectionName(); } diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/Composable.java b/nitrite/src/main/java/org/dizitart/no2/migration/Composable.java deleted file mode 100644 index 74d49c7a9..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/migration/Composable.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.dizitart.no2.migration; - -/** - * @author Anindya Chatterjee - */ -interface Composable { - void addStep(MigrationStep step); -} diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/CustomInstruction.java b/nitrite/src/main/java/org/dizitart/no2/migration/CustomInstruction.java index 637a7bc1d..5995afc94 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/CustomInstruction.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/CustomInstruction.java @@ -3,8 +3,16 @@ import org.dizitart.no2.Nitrite; /** + * Represents a custom instruction for database migration. + * * @author Anindya Chatterjee + * @since 4.0 */ public interface CustomInstruction { + /** + * Performs the instruction on the nitrite database. + * + * @param nitrite the nitrite database + */ void perform(Nitrite nitrite); } diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/DatabaseInstruction.java b/nitrite/src/main/java/org/dizitart/no2/migration/DatabaseInstruction.java index 9373308f2..3f6f919e4 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/DatabaseInstruction.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/DatabaseInstruction.java @@ -5,10 +5,20 @@ import org.dizitart.no2.common.util.SecureString; /** + * Represents a migration instruction set for the nitrite database. + * * @author Anindya Chatterjee + * @since 4.0 */ -public interface DatabaseInstruction extends Composable { +public interface DatabaseInstruction extends Instruction { + /** + * Adds an instruction to set an user authentication to the database. + * + * @param username the username + * @param password the password + * @return the database instruction + */ default DatabaseInstruction addPassword(String username, String password) { MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.AddPassword); @@ -17,6 +27,14 @@ default DatabaseInstruction addPassword(String username, String password) { return this; } + /** + * Adds an instruction to change the password for the user authentication to the database. + * + * @param username the username + * @param oldPassword the old password + * @param newPassword the new password + * @return the database instruction + */ default DatabaseInstruction changePassword(String username, String oldPassword, String newPassword) { MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.ChangePassword); @@ -25,6 +43,12 @@ default DatabaseInstruction changePassword(String username, String oldPassword, return this; } + /** + * Adds an instruction to drop a {@link org.dizitart.no2.collection.NitriteCollection} from the database. + * + * @param collectionName the collection name + * @return the database instruction + */ default DatabaseInstruction dropCollection(String collectionName) { MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.DropCollection); @@ -33,18 +57,44 @@ default DatabaseInstruction dropCollection(String collectionName) { return this; } + /** + * Adds an instruction to drop an {@link org.dizitart.no2.repository.ObjectRepository} from the database. + * + * @param type the type + * @return the database instruction + */ default DatabaseInstruction dropRepository(Class type) { return dropRepository(type.getName()); } + /** + * Adds an instruction to drop an {@link org.dizitart.no2.repository.ObjectRepository} from the database. + * + * @param typeName the type name + * @return the database instruction + */ default DatabaseInstruction dropRepository(String typeName) { return dropRepository(typeName, null); } + /** + * Adds an instruction to drop a keyed {@link org.dizitart.no2.repository.ObjectRepository} from the database. + * + * @param type the type + * @param key the key + * @return the database instruction + */ default DatabaseInstruction dropRepository(Class type, String key) { return dropRepository(type.getName(), key); } + /** + * Adds an instruction to drop a keyed {@link org.dizitart.no2.repository.ObjectRepository} from the database. + * + * @param typeName the type name + * @param key the key + * @return the database instruction + */ default DatabaseInstruction dropRepository(String typeName, String key) { MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.DropRepository); @@ -53,6 +103,12 @@ default DatabaseInstruction dropRepository(String typeName, String key) { return this; } + /** + * Adds a custom instruction to perform a user defined operation on the database. + * + * @param instruction the instruction + * @return the database instruction + */ default DatabaseInstruction customInstruction(CustomInstruction instruction) { MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.Custom); diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/Generator.java b/nitrite/src/main/java/org/dizitart/no2/migration/Generator.java index 039fde65a..66fff74e0 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/Generator.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/Generator.java @@ -3,8 +3,18 @@ import org.dizitart.no2.collection.Document; /** + * Represents a default value generator for the document fields during field manipulation instruction. + * + * @param the type parameter * @author Anindya Chatterjee + * @since 4.0 */ public interface Generator { + /** + * Generates a new value for a field in the document. + * + * @param document the document + * @return the value + */ T generate(Document document); } diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/Instruction.java b/nitrite/src/main/java/org/dizitart/no2/migration/Instruction.java index 821055bcf..f9af0e355 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/Instruction.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/Instruction.java @@ -1,26 +1,16 @@ package org.dizitart.no2.migration; -import static org.dizitart.no2.common.util.ObjectUtils.getEntityName; - /** + * Represents a collection of database migration steps. + * * @author Anindya Chatterjee + * @since 4.0 */ -public interface Instruction { - DatabaseInstruction forDatabase(); - - default RepositoryInstruction forRepository(String typeName) { - return forRepository(typeName, null); - } - - default RepositoryInstruction forRepository(Class type) { - return forRepository(getEntityName(type), null); - } - - default RepositoryInstruction forRepository(Class type, String key) { - return forRepository(getEntityName(type), key); - } - - RepositoryInstruction forRepository(String typeName, String key); - - CollectionInstruction forCollection(String collectionName); +interface Instruction { + /** + * Adds a migration step to the instruction set. + * + * @param step the step + */ + void addStep(MigrationStep step); } diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/InstructionType.java b/nitrite/src/main/java/org/dizitart/no2/migration/InstructionType.java index 0489b514a..3fc8a927e 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/InstructionType.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/InstructionType.java @@ -1,33 +1,101 @@ package org.dizitart.no2.migration; /** + * Represents an instruction type. + * * @author Anindya Chatterjee + * @since 4.0 */ public enum InstructionType { // db related statements + /** + * The add password instruction. + */ AddPassword, + /** + * The change password instruction. + */ ChangePassword, + /** + * The drop collection instruction. + */ DropCollection, + /** + * The drop repository instruction. + */ DropRepository, + /** + * The custom instruction. + */ Custom, + // collection related statements + /** + * The collection rename instruction. + */ CollectionRename, + /** + * The collection add field instruction. + */ CollectionAddField, + /** + * The collection rename field instruction. + */ CollectionRenameField, + /** + * The collection delete field instruction. + */ CollectionDeleteField, + /** + * The collection drop index instruction. + */ CollectionDropIndex, + /** + * The collection drop all indices instruction. + */ CollectionDropIndices, + /** + * The collection create index instruction. + */ CollectionCreateIndex, + // repository related statements + /** + * The rename repository instruction. + */ RenameRepository, + /** + * The repository add field instruction. + */ RepositoryAddField, + /** + * The repository rename field instruction. + */ RepositoryRenameField, + /** + * The repository delete field instruction. + */ RepositoryDeleteField, + /** + * The repository change data type instruction. + */ RepositoryChangeDataType, + /** + * The repository change id field instruction. + */ RepositoryChangeIdField, + /** + * The repository drop index instruction. + */ RepositoryDropIndex, + /** + * The repository drop indices instruction. + */ RepositoryDropIndices, + /** + * The repository create index instruction. + */ RepositoryCreateIndex } diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/Instructions.java b/nitrite/src/main/java/org/dizitart/no2/migration/Instructions.java new file mode 100644 index 000000000..5f98c267e --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/migration/Instructions.java @@ -0,0 +1,66 @@ +package org.dizitart.no2.migration; + +import static org.dizitart.no2.common.util.ObjectUtils.getEntityName; + +/** + * Represents a set of instruction to perform during database migration. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +public interface Instructions { + /** + * Creates a {@link DatabaseInstruction}. + * + * @return the database instruction + */ + DatabaseInstruction forDatabase(); + + /** + * Creates a {@link RepositoryInstruction}. + * + * @param typeName the type name + * @return the repository instruction + */ + default RepositoryInstruction forRepository(String typeName) { + return forRepository(typeName, null); + } + + /** + * Creates a {@link RepositoryInstruction}. + * + * @param type the type + * @return the repository instruction + */ + default RepositoryInstruction forRepository(Class type) { + return forRepository(getEntityName(type), null); + } + + /** + * Creates a {@link RepositoryInstruction}. + * + * @param type the type + * @param key the key + * @return the repository instruction + */ + default RepositoryInstruction forRepository(Class type, String key) { + return forRepository(getEntityName(type), key); + } + + /** + * Creates a {@link RepositoryInstruction}. + * + * @param typeName the type name + * @param key the key + * @return the repository instruction + */ + RepositoryInstruction forRepository(String typeName, String key); + + /** + * Creates a {@link CollectionInstruction}. + * + * @param collectionName the collection name + * @return the collection instruction + */ + CollectionInstruction forCollection(String collectionName); +} diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/Migration.java b/nitrite/src/main/java/org/dizitart/no2/migration/Migration.java index 3c9cd7333..92af007be 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/Migration.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/Migration.java @@ -6,7 +6,10 @@ import java.util.Queue; /** + * Represents the database migration operation. + * * @author Anindya Chatterjee + * @since 4.0 */ public abstract class Migration { private final Queue migrationSteps; @@ -19,14 +22,30 @@ public abstract class Migration { private boolean executed = false; + /** + * Instantiates a new {@link Migration}. + * + * @param startVersion the start version + * @param endVersion the end version + */ public Migration(Integer startVersion, Integer endVersion) { this.startVersion = startVersion; this.endVersion = endVersion; this.migrationSteps = new LinkedList<>(); } - public abstract void migrate(Instruction instruction); - + /** + * Migrates the database using the instructions. + * + * @param instructions the instructions + */ + public abstract void migrate(Instructions instructions); + + /** + * Returns the {@link MigrationStep}s as a queue for execution. + * + * @return the queue + */ public Queue steps() { if (!executed) { execute(); @@ -35,7 +54,7 @@ public Queue steps() { } private void execute() { - NitriteInstruction instruction = new NitriteInstruction(migrationSteps); + NitriteInstructions instruction = new NitriteInstructions(migrationSteps); migrate(instruction); this.executed = true; } diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/MigrationManager.java b/nitrite/src/main/java/org/dizitart/no2/migration/MigrationManager.java index 9cbcd97fa..7da5cea89 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/MigrationManager.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/MigrationManager.java @@ -3,15 +3,17 @@ import org.dizitart.no2.Nitrite; import org.dizitart.no2.NitriteConfig; import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.Fields; import org.dizitart.no2.common.tuples.Pair; import org.dizitart.no2.common.tuples.Quartet; import org.dizitart.no2.common.tuples.Triplet; import org.dizitart.no2.common.util.SecureString; import org.dizitart.no2.exceptions.MigrationException; +import org.dizitart.no2.exceptions.NitriteIOException; import org.dizitart.no2.migration.commands.*; -import org.dizitart.no2.store.DatabaseMetaData; +import org.dizitart.no2.store.StoreMetaData; import org.dizitart.no2.store.NitriteMap; -import org.dizitart.no2.store.StoreSecurity; +import org.dizitart.no2.store.UserAuthenticationService; import java.util.LinkedList; import java.util.Queue; @@ -22,31 +24,46 @@ import static org.dizitart.no2.common.util.ObjectUtils.findRepositoryName; /** + * The database migration manager. + * * @author Anindya Chatterjee + * @since 4.0 */ public class MigrationManager { private final NitriteConfig nitriteConfig; - private final DatabaseMetaData databaseMetadata; + private final StoreMetaData storeMetadata; private final Nitrite database; + /** + * Instantiates a new {@link MigrationManager}. + * + * @param nitrite the nitrite database + */ public MigrationManager(Nitrite nitrite) { this.database = nitrite; this.nitriteConfig = nitrite.getConfig(); - this.databaseMetadata = nitrite.getDatabaseMetaData(); + this.storeMetadata = nitrite.getDatabaseMetaData(); } + /** + * Performs the migration on the database. + */ public void doMigrate() { if (isMigrationNeeded()) { - Integer existingVersion = databaseMetadata.getSchemaVersion(); + Integer existingVersion = storeMetadata.getSchemaVersion(); Integer incomingVersion = nitriteConfig.getSchemaVersion(); Queue migrationPath = findMigrationPath(existingVersion, incomingVersion); if (migrationPath == null || migrationPath.isEmpty()) { // close the database - database.close(); + try { + database.close(); + } catch (Exception e) { + throw new NitriteIOException("failed to close the database", e); + } throw new MigrationException("schema version mismatch, as no migration path found from version " - + databaseMetadata.getSchemaVersion() + " to " + nitriteConfig.getSchemaVersion()); + + storeMetadata.getSchemaVersion() + " to " + nitriteConfig.getSchemaVersion()); } int length = migrationPath.size(); @@ -61,7 +78,7 @@ public void doMigrate() { } private boolean isMigrationNeeded() { - Integer existingVersion = databaseMetadata.getSchemaVersion(); + Integer existingVersion = storeMetadata.getSchemaVersion(); Integer incomingVersion = nitriteConfig.getSchemaVersion(); if (existingVersion == null) { @@ -129,7 +146,7 @@ private void executeMigrationSteps(Queue migrationSteps) { } } - DatabaseMetaData metaData = database.getDatabaseMetaData(); + StoreMetaData metaData = database.getDatabaseMetaData(); metaData.setSchemaVersion(nitriteConfig.getSchemaVersion()); NitriteMap storeInfo = database.getStore().openMap(STORE_INFO, @@ -145,15 +162,20 @@ private void executeStep(MigrationStep step) { case AddPassword: Pair arg1 = (Pair) step.getArguments(); - command = nitrite -> StoreSecurity.addOrUpdatePassword(nitrite.getStore(), - false, arg1.getFirst(), null, arg1.getSecond()); + command = nitrite -> { + UserAuthenticationService authService = new UserAuthenticationService(nitrite.getStore()); + authService.addOrUpdatePassword(false, arg1.getFirst(), + null, arg1.getSecond()); + }; break; case ChangePassword: Triplet arg2 = (Triplet) step.getArguments(); - command = nitrite -> StoreSecurity.addOrUpdatePassword(nitrite.getStore(), - true, arg2.getFirst(), arg2.getSecond(), arg2.getThird()); + command = nitrite -> { + UserAuthenticationService authService = new UserAuthenticationService(nitrite.getStore()); + authService.addOrUpdatePassword(true, arg2.getFirst(), arg2.getSecond(), arg2.getThird()); + }; break; case DropCollection: @@ -192,7 +214,7 @@ private void executeStep(MigrationStep step) { break; case CollectionDropIndex: - Pair arg9 = (Pair) step.getArguments(); + Pair arg9 = (Pair) step.getArguments(); command = new DropIndex(arg9.getFirst(), arg9.getSecond()); break; @@ -202,7 +224,7 @@ private void executeStep(MigrationStep step) { break; case CollectionCreateIndex: - Triplet arg10 = (Triplet) step.getArguments(); + Triplet arg10 = (Triplet) step.getArguments(); command = new CreateIndex(arg10.getFirst(), arg10.getSecond(), arg10.getThird()); break; @@ -241,14 +263,14 @@ private void executeStep(MigrationStep step) { break; case RepositoryChangeIdField: - Quartet arg17 = - (Quartet) step.getArguments(); + Quartet arg17 = + (Quartet) step.getArguments(); command = new ChangeIdField(findRepositoryName(arg17.getFirst(), arg17.getSecond()), arg17.getThird(), arg17.getFourth()); break; case RepositoryDropIndex: - Triplet arg18 = (Triplet) step.getArguments(); + Triplet arg18 = (Triplet) step.getArguments(); command = new DropIndex(findRepositoryName(arg18.getFirst(), arg18.getSecond()), arg18.getThird()); break; @@ -258,8 +280,8 @@ private void executeStep(MigrationStep step) { break; case RepositoryCreateIndex: - Quartet arg20 = - (Quartet) step.getArguments(); + Quartet arg20 = + (Quartet) step.getArguments(); command = new CreateIndex(findRepositoryName(arg20.getFirst(), arg20.getSecond()), arg20.getThird(), arg20.getFourth()); break; diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/MigrationStep.java b/nitrite/src/main/java/org/dizitart/no2/migration/MigrationStep.java index ccabc1459..0d9c059ff 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/MigrationStep.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/MigrationStep.java @@ -6,7 +6,10 @@ import lombok.Setter; /** + * Represents a migration step. + * * @author Anindya Chatterjee + * @since 4.0 */ @Getter(AccessLevel.PACKAGE) @Setter(AccessLevel.PACKAGE) diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/NitriteInstruction.java b/nitrite/src/main/java/org/dizitart/no2/migration/NitriteInstruction.java deleted file mode 100644 index e49d0d91b..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/migration/NitriteInstruction.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.dizitart.no2.migration; - -import lombok.AccessLevel; -import lombok.Getter; - -import java.util.Queue; - -/** - * @author Anindya Chatterjee - */ -class NitriteInstruction implements Instruction { - @Getter(AccessLevel.PACKAGE) - private final Queue migrationSteps; - - NitriteInstruction(Queue migrationSteps) { - this.migrationSteps = migrationSteps; - } - - @Override - public DatabaseInstruction forDatabase() { - return migrationSteps::add; - } - - @Override - public RepositoryInstruction forRepository(String typeName, String key) { - return new RepositoryInstruction() { - @Override - public String entityName() { - return typeName; - } - - @Override - public String key() { - return key; - } - - @Override - public void addStep(MigrationStep step) { - migrationSteps.add(step); - } - }; - } - - @Override - public CollectionInstruction forCollection(String collectionName) { - return new CollectionInstruction() { - @Override - public String collectionName() { - return collectionName; - } - - @Override - public void addStep(MigrationStep step) { - migrationSteps.add(step); - } - }; - } -} diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/NitriteInstructions.java b/nitrite/src/main/java/org/dizitart/no2/migration/NitriteInstructions.java new file mode 100644 index 000000000..3dade87ec --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/migration/NitriteInstructions.java @@ -0,0 +1,61 @@ +package org.dizitart.no2.migration; + +import lombok.AccessLevel; +import lombok.Getter; + +import java.util.Queue; + +/** + * Default implementation of {@link Instructions}. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +class NitriteInstructions implements Instructions { + @Getter(AccessLevel.PACKAGE) + private final Queue migrationSteps; + + NitriteInstructions(Queue migrationSteps) { + this.migrationSteps = migrationSteps; + } + + @Override + public DatabaseInstruction forDatabase() { + return migrationSteps::add; + } + + @Override + public RepositoryInstruction forRepository(String typeName, String key) { + return new RepositoryInstruction() { + @Override + public String entityName() { + return typeName; + } + + @Override + public String key() { + return key; + } + + @Override + public void addStep(MigrationStep step) { + migrationSteps.add(step); + } + }; + } + + @Override + public CollectionInstruction forCollection(String collectionName) { + return new CollectionInstruction() { + @Override + public String collectionName() { + return collectionName; + } + + @Override + public void addStep(MigrationStep step) { + migrationSteps.add(step); + } + }; + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/RepositoryInstruction.java b/nitrite/src/main/java/org/dizitart/no2/migration/RepositoryInstruction.java index a4f3ffad7..7dd160cac 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/RepositoryInstruction.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/RepositoryInstruction.java @@ -1,14 +1,27 @@ package org.dizitart.no2.migration; +import org.dizitart.no2.common.Fields; import org.dizitart.no2.common.tuples.Pair; import org.dizitart.no2.common.tuples.Quartet; import org.dizitart.no2.common.tuples.Triplet; +import java.util.List; + /** + * Represents a migration instruction set for {@link org.dizitart.no2.repository.ObjectRepository}. + * * @author Anindya Chatterjee + * @since 4.0 */ -public interface RepositoryInstruction extends Composable { - +public interface RepositoryInstruction extends Instruction { + + /** + * Adds an instruction to rename the {@link org.dizitart.no2.repository.ObjectRepository}. + * + * @param entityName the entity name + * @param key the key + * @return the repository instruction + */ default RepositoryInstruction renameRepository(String entityName, String key) { MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.RenameRepository); @@ -34,10 +47,27 @@ public void addStep(MigrationStep step) { }; } + /** + * Adds an instruction to add new field to the entity in + * the {@link org.dizitart.no2.repository.ObjectRepository}. + * + * @param the type parameter + * @param fieldName the field name + * @return the repository instruction + */ default RepositoryInstruction addField(String fieldName) { return addField(fieldName, null); } + /** + * Adds an instruction to add new field with a default value, into the entity in the + * {@link org.dizitart.no2.repository.ObjectRepository}. + * + * @param the type parameter + * @param fieldName the field name + * @param defaultValue the default value + * @return the repository instruction + */ default RepositoryInstruction addField(String fieldName, T defaultValue) { MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.RepositoryAddField); @@ -46,6 +76,15 @@ default RepositoryInstruction addField(String fieldName, T defaultValue) { return this; } + /** + * Adds an instruction to add new field with value generator, into the entity in + * the {@link org.dizitart.no2.repository.ObjectRepository}. + * + * @param the type parameter + * @param fieldName the field name + * @param generator the generator + * @return the repository instruction + */ default RepositoryInstruction addField(String fieldName, Generator generator) { MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.RepositoryAddField); @@ -54,6 +93,14 @@ default RepositoryInstruction addField(String fieldName, Generator genera return this; } + /** + * Adds an instruction to rename a field to the entity in the + * {@link org.dizitart.no2.repository.ObjectRepository}. + * + * @param oldName the old name + * @param newName the new name + * @return the repository instruction + */ default RepositoryInstruction renameField(String oldName, String newName) { MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.RepositoryRenameField); @@ -62,6 +109,13 @@ default RepositoryInstruction renameField(String oldName, String newName) { return this; } + /** + * Adds an instruction to delete a field from the entity in + * the {@link org.dizitart.no2.repository.ObjectRepository}. + * + * @param fieldName the field name + * @return the repository instruction + */ default RepositoryInstruction deleteField(String fieldName) { MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.RepositoryDeleteField); @@ -70,7 +124,15 @@ default RepositoryInstruction deleteField(String fieldName) { return this; } - default RepositoryInstruction changeDataType(String fieldName, TypeConverter converter) { + /** + * Adds an instruction to change the datatype of a field of the entity in + * the {@link org.dizitart.no2.repository.ObjectRepository}. + * + * @param fieldName the field name + * @param converter the converter + * @return the repository instruction + */ + default RepositoryInstruction changeDataType(String fieldName, TypeConverter converter) { MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.RepositoryChangeDataType); migrationStep.setArguments(new Quartet<>(entityName(), key(), fieldName, converter)); @@ -78,22 +140,58 @@ default RepositoryInstruction changeDataType(String fieldName, TypeConverter return this; } - default RepositoryInstruction changeIdField(String oldFieldName, String newFieldName) { + /** + * Adds an instruction to change the id field of an entity in the + * {@link org.dizitart.no2.repository.ObjectRepository} + * + * @param oldFieldNames the old field names + * @param newFieldNames the new field names + * @return the repository instruction + */ + default RepositoryInstruction changeIdField(List oldFieldNames, List newFieldNames) { + Fields oldFields = Fields.withNames(oldFieldNames.toArray(new String[0])); + Fields newFields = Fields.withNames(newFieldNames.toArray(new String[0])); + return changeIdField(oldFields, newFields); + } + + /** + * Adds an instruction to change the id field of an entity in the + * {@link org.dizitart.no2.repository.ObjectRepository} + * + * @param oldField the old field names + * @param newField the new field names + * @return the repository instruction + */ + default RepositoryInstruction changeIdField(Fields oldField, Fields newField) { MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.RepositoryChangeIdField); - migrationStep.setArguments(new Quartet<>(entityName(), key(), oldFieldName, newFieldName)); + migrationStep.setArguments(new Quartet<>(entityName(), key(), oldField, newField)); addStep(migrationStep); return this; } - default RepositoryInstruction dropIndex(String field) { + + + /** + * Adds an instruction to drop an index from the {@link org.dizitart.no2.repository.ObjectRepository}. + * + * @param fieldNames the field names + * @return the repository instruction + */ + default RepositoryInstruction dropIndex(String... fieldNames) { + Fields fields = Fields.withNames(fieldNames); MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.RepositoryDropIndex); - migrationStep.setArguments(new Triplet<>(entityName(), key(), field)); + migrationStep.setArguments(new Triplet<>(entityName(), key(), fields)); addStep(migrationStep); return this; } + /** + * Adds an instruction to drop all indices from the {@link org.dizitart.no2.repository.ObjectRepository}. + * + * @return the repository instruction + */ default RepositoryInstruction dropAllIndices() { MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.RepositoryDropIndices); @@ -102,15 +200,33 @@ default RepositoryInstruction dropAllIndices() { return this; } - default RepositoryInstruction createIndex(String field, String indexType) { + /** + * Adds an instruction to create an index in the {@link org.dizitart.no2.repository.ObjectRepository}. + * + * @param indexType the index type + * @param fieldNames the field names + * @return the repository instruction + */ + default RepositoryInstruction createIndex(String indexType, String... fieldNames) { + Fields fields = Fields.withNames(fieldNames); MigrationStep migrationStep = new MigrationStep(); migrationStep.setInstructionType(InstructionType.RepositoryCreateIndex); - migrationStep.setArguments(new Quartet<>(entityName(), key(), field, indexType)); + migrationStep.setArguments(new Quartet<>(entityName(), key(), fields, indexType)); addStep(migrationStep); return this; } + /** + * The entity name of the {@link org.dizitart.no2.repository.ObjectRepository}. + * + * @return the string + */ String entityName(); + /** + * The key of the {@link org.dizitart.no2.repository.ObjectRepository}. + * + * @return the string + */ String key(); } diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/TypeConverter.java b/nitrite/src/main/java/org/dizitart/no2/migration/TypeConverter.java index 74b8bbbfb..d52d36162 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/TypeConverter.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/TypeConverter.java @@ -1,8 +1,19 @@ package org.dizitart.no2.migration; /** + * Represents a type converter. + * + * @param the type parameter + * @param the type parameter * @author Anindya Chatterjee + * @since 4.0 */ public interface TypeConverter { + /** + * Converts an object of type S to an object of type T. + * + * @param source the source + * @return the target object + */ T convert(S source); } diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/commands/AddField.java b/nitrite/src/main/java/org/dizitart/no2/migration/commands/AddField.java index db7c6fb48..b9c6fe4c2 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/commands/AddField.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/commands/AddField.java @@ -4,8 +4,9 @@ import org.dizitart.no2.Nitrite; import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.Fields; import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.index.IndexEntry; +import org.dizitart.no2.index.IndexDescriptor; import org.dizitart.no2.migration.Generator; /** @@ -21,7 +22,7 @@ public class AddField extends BaseCommand implements Command { public void execute(Nitrite nitrite) { initialize(nitrite, collectionName); - IndexEntry indexEntry = indexCatalog.findIndexEntry(collectionName, fieldName); + IndexDescriptor indexDescriptor = operations.findIndex(Fields.withNames(fieldName)); for (Pair pair : nitriteMap.entries()) { Document document = pair.getSecond(); @@ -34,8 +35,8 @@ public void execute(Nitrite nitrite) { nitriteMap.put(pair.getFirst(), document); } - if (indexEntry != null) { - operations.createIndex(fieldName, indexEntry.getIndexType(), false); + if (indexDescriptor != null) { + operations.createIndex(Fields.withNames(fieldName), indexDescriptor.getIndexType()); } } } diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/commands/BaseCommand.java b/nitrite/src/main/java/org/dizitart/no2/migration/commands/BaseCommand.java index 3e273f8a0..db6cade49 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/commands/BaseCommand.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/commands/BaseCommand.java @@ -4,22 +4,40 @@ import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.collection.operation.CollectionOperations; -import org.dizitart.no2.store.IndexCatalog; import org.dizitart.no2.store.NitriteMap; import org.dizitart.no2.store.NitriteStore; /** + * Represents a base command for database migration. It initializes + * different components necessary to execute the migration steps + * * @author Anindya Chatterjee + * @since 4.0 */ abstract class BaseCommand implements Command { + /** + * The nitrite store. + */ protected NitriteStore nitriteStore; - protected IndexCatalog indexCatalog; + + /** + * The nitrite map. + */ protected NitriteMap nitriteMap; + + /** + * The collection operations. + */ protected CollectionOperations operations; + /** + * Initializes the database for migration. + * + * @param nitrite the nitrite + * @param collectionName the collection name + */ void initialize(Nitrite nitrite, String collectionName) { nitriteStore = nitrite.getStore(); - indexCatalog = nitriteStore.getIndexCatalog(); nitriteMap = nitriteStore.openMap(collectionName, NitriteId.class, Document.class); operations = new CollectionOperations(collectionName, nitriteMap, nitrite.getConfig(), null); diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/commands/ChangeDataType.java b/nitrite/src/main/java/org/dizitart/no2/migration/commands/ChangeDataType.java index 9c34d4bf7..ec0685aa7 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/commands/ChangeDataType.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/commands/ChangeDataType.java @@ -4,12 +4,17 @@ import org.dizitart.no2.Nitrite; import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.Fields; import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.index.IndexEntry; +import org.dizitart.no2.index.IndexDescriptor; import org.dizitart.no2.migration.TypeConverter; /** + * A migration command to change the datatype of a document field + * in a collection. + * * @author Anindya Chatterjee + * @since 4.0 */ @AllArgsConstructor @SuppressWarnings({"unchecked", "rawtypes"}) @@ -31,9 +36,9 @@ public void execute(Nitrite nitrite) { nitriteMap.put(entry.getFirst(), document); } - IndexEntry indexEntry = indexCatalog.findIndexEntry(collectionName, fieldName); - if (indexEntry != null) { - operations.rebuildIndex(indexEntry, false); + IndexDescriptor indexDescriptor = operations.findIndex(Fields.withNames(fieldName)); + if (indexDescriptor != null) { + operations.rebuildIndex(indexDescriptor); } } } \ No newline at end of file diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/commands/ChangeIdField.java b/nitrite/src/main/java/org/dizitart/no2/migration/commands/ChangeIdField.java index 18bfbc4f9..3eb56806b 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/commands/ChangeIdField.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/commands/ChangeIdField.java @@ -2,26 +2,31 @@ import lombok.AllArgsConstructor; import org.dizitart.no2.Nitrite; +import org.dizitart.no2.common.Fields; import org.dizitart.no2.index.IndexType; /** + * A command to change the id fields of an entity in + * an {@link org.dizitart.no2.repository.ObjectRepository}. + * * @author Anindya Chatterjee + * @since 4.0 */ @AllArgsConstructor public class ChangeIdField extends BaseCommand implements Command { private final String collectionName; - private final String oldFieldName; - private final String newFieldName; + private final Fields oldFields; + private final Fields newFields; @Override public void execute(Nitrite nitrite) { initialize(nitrite, collectionName); - boolean hasIndex = operations.hasIndex(oldFieldName); + boolean hasIndex = operations.hasIndex(oldFields); if (hasIndex) { - operations.dropIndex(oldFieldName); + operations.dropIndex(oldFields); } - operations.createIndex(newFieldName, IndexType.Unique, false); + operations.createIndex(newFields, IndexType.UNIQUE); } } \ No newline at end of file diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/commands/Command.java b/nitrite/src/main/java/org/dizitart/no2/migration/commands/Command.java index bc9e5788c..7d3c7b0db 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/commands/Command.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/commands/Command.java @@ -3,8 +3,16 @@ import org.dizitart.no2.Nitrite; /** + * Represents a database migration command. + * * @author Anindya Chatterjee + * @since 4.0 */ public interface Command { + /** + * Executes a migration step on the database. + * + * @param nitrite the nitrite database instance + */ void execute(Nitrite nitrite); } diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/commands/CreateIndex.java b/nitrite/src/main/java/org/dizitart/no2/migration/commands/CreateIndex.java index 3d6772979..3081a613a 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/commands/CreateIndex.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/commands/CreateIndex.java @@ -2,20 +2,24 @@ import lombok.AllArgsConstructor; import org.dizitart.no2.Nitrite; +import org.dizitart.no2.common.Fields; /** + * A command to create an index. + * * @author Anindya Chatterjee + * @since 4.0 */ @AllArgsConstructor public class CreateIndex extends BaseCommand implements Command { private final String collectionName; - private final String fieldName; + private final Fields fields; private final String indexType; @Override public void execute(Nitrite nitrite) { initialize(nitrite, collectionName); - operations.createIndex(fieldName, indexType, false); + operations.createIndex(fields, indexType); } } diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/commands/DeleteField.java b/nitrite/src/main/java/org/dizitart/no2/migration/commands/DeleteField.java index b9a4f0272..9826e7d38 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/commands/DeleteField.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/commands/DeleteField.java @@ -4,11 +4,16 @@ import org.dizitart.no2.Nitrite; import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.Fields; import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.index.IndexEntry; +import org.dizitart.no2.index.IndexDescriptor; /** + * A command to delete a field from the document of + * a collection. + * * @author Anindya Chatterjee + * @since 4.0 */ @AllArgsConstructor public class DeleteField extends BaseCommand implements Command { @@ -19,15 +24,15 @@ public class DeleteField extends BaseCommand implements Command { public void execute(Nitrite nitrite) { initialize(nitrite, collectionName); - IndexEntry indexEntry = indexCatalog.findIndexEntry(collectionName, fieldName); + IndexDescriptor indexDescriptor = operations.findIndex(Fields.withNames(fieldName)); for (Pair entry : nitriteMap.entries()) { Document document = entry.getSecond(); document.remove(fieldName); nitriteMap.put(entry.getFirst(), document); } - if (indexEntry != null) { - operations.dropIndex(fieldName); + if (indexDescriptor != null) { + operations.dropIndex(Fields.withNames(fieldName)); } } } diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/commands/Drop.java b/nitrite/src/main/java/org/dizitart/no2/migration/commands/Drop.java index 4f7e6f1ab..c8bf6cc42 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/commands/Drop.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/commands/Drop.java @@ -4,7 +4,10 @@ import org.dizitart.no2.Nitrite; /** + * A command to drop a nitrite collection. + * * @author Anindya Chatterjee + * @since 4.0 */ @AllArgsConstructor public class Drop extends BaseCommand implements Command { diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/commands/DropIndex.java b/nitrite/src/main/java/org/dizitart/no2/migration/commands/DropIndex.java index 761d07c42..ca242840a 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/commands/DropIndex.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/commands/DropIndex.java @@ -2,25 +2,27 @@ import lombok.AllArgsConstructor; import org.dizitart.no2.Nitrite; - -import static org.dizitart.no2.common.util.StringUtils.isNullOrEmpty; +import org.dizitart.no2.common.Fields; /** + * A command to drop an index. + * * @author Anindya Chatterjee + * @since 4.0 */ @AllArgsConstructor public class DropIndex extends BaseCommand implements Command { private final String collectionName; - private final String fieldName; + private final Fields fields; @Override public void execute(Nitrite nitrite) { initialize(nitrite, collectionName); - if (isNullOrEmpty(fieldName)) { + if (fields == null) { operations.dropAllIndices(); } else { - operations.dropIndex(fieldName); + operations.dropIndex(fields); } } } diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/commands/Rename.java b/nitrite/src/main/java/org/dizitart/no2/migration/commands/Rename.java index 4092710b8..5839867c0 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/commands/Rename.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/commands/Rename.java @@ -5,15 +5,19 @@ import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.collection.operation.CollectionOperations; +import org.dizitart.no2.collection.operation.IndexManager; +import org.dizitart.no2.common.Fields; import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.index.IndexEntry; -import org.dizitart.no2.store.IndexCatalog; +import org.dizitart.no2.index.IndexDescriptor; import org.dizitart.no2.store.NitriteMap; import java.util.Collection; /** + * A command to rename a {@link org.dizitart.no2.collection.NitriteCollection}. + * * @author Anindya Chatterjee + * @since 4.0 */ @AllArgsConstructor public class Rename extends BaseCommand implements Command { @@ -31,12 +35,12 @@ public void execute(Nitrite nitrite) { newMap.put(entry.getFirst(), entry.getSecond()); } - IndexCatalog indexCatalog = nitrite.getStore().getIndexCatalog(); - Collection indexEntries = indexCatalog.listIndexEntries(oldName); - for (IndexEntry indexEntry : indexEntries) { - String field = indexEntry.getField(); - String indexType = indexEntry.getIndexType(); - newOperations.createIndex(field, indexType, false); + IndexManager indexManager = new IndexManager(oldName, nitrite.getConfig()); + Collection indexEntries = indexManager.getIndexDescriptors(); + for (IndexDescriptor indexDescriptor : indexEntries) { + Fields field = indexDescriptor.getIndexFields(); + String indexType = indexDescriptor.getIndexType(); + newOperations.createIndex(field, indexType); } operations.dropCollection(); diff --git a/nitrite/src/main/java/org/dizitart/no2/migration/commands/RenameField.java b/nitrite/src/main/java/org/dizitart/no2/migration/commands/RenameField.java index 15631ce0a..7475c5599 100644 --- a/nitrite/src/main/java/org/dizitart/no2/migration/commands/RenameField.java +++ b/nitrite/src/main/java/org/dizitart/no2/migration/commands/RenameField.java @@ -4,12 +4,18 @@ import org.dizitart.no2.Nitrite; import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.collection.operation.IndexManager; +import org.dizitart.no2.common.Fields; import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.index.IndexEntry; -import org.dizitart.no2.store.IndexCatalog; +import org.dizitart.no2.index.IndexDescriptor; + +import java.util.Collection; /** + * A command to rename a document field. + * * @author Anindya Chatterjee + * @since 4.0 */ @AllArgsConstructor public class RenameField extends BaseCommand implements Command { @@ -21,7 +27,10 @@ public class RenameField extends BaseCommand implements Command { public void execute(Nitrite nitrite) { initialize(nitrite, collectionName); - boolean indexExists = indexCatalog.hasIndexEntry(collectionName, oldName); + IndexManager indexManager = new IndexManager(oldName, nitrite.getConfig()); + Fields oldField = Fields.withNames(oldName); + Collection matchingIndexDescriptors = indexManager.findMatchingIndexDescriptors(oldField); + for (Pair entry : nitriteMap.entries()) { Document document = entry.getSecond(); if (document.containsKey(oldName)) { @@ -33,13 +42,27 @@ public void execute(Nitrite nitrite) { } } - if (indexExists) { - IndexCatalog indexCatalog = nitrite.getStore().getIndexCatalog(); - IndexEntry indexEntry = indexCatalog.findIndexEntry(collectionName, oldName); - String indexType = indexEntry.getIndexType(); + if (!matchingIndexDescriptors.isEmpty()) { + for (IndexDescriptor matchingIndexDescriptor : matchingIndexDescriptors) { + String indexType = matchingIndexDescriptor.getIndexType(); - operations.dropIndex(oldName); - operations.createIndex(newName, indexType, false); + Fields oldIndexFields = matchingIndexDescriptor.getIndexFields(); + Fields newIndexFields = getNewIndexFields(oldIndexFields, oldName, newName); + operations.dropIndex(matchingIndexDescriptor.getIndexFields()); + operations.createIndex(newIndexFields, indexType); + } + } + } + + private Fields getNewIndexFields(Fields oldIndexFields, String oldName, String newName) { + Fields newIndexFields = new Fields(); + for (String fieldName : oldIndexFields.getFieldNames()) { + if (fieldName.equals(oldName)) { + newIndexFields.addField(newName); + } else { + newIndexFields.addField(fieldName); + } } + return newIndexFields; } } diff --git a/nitrite/src/main/java/org/dizitart/no2/module/NitriteModule.java b/nitrite/src/main/java/org/dizitart/no2/module/NitriteModule.java deleted file mode 100644 index 64e2b52d2..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/module/NitriteModule.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.module; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -/** - * @author Anindya Chatterjee - */ -public interface NitriteModule { - static NitriteModule module(NitritePlugin... plugins) { - return new NitriteModule() { - @Override - public Set plugins() { - return setOf(plugins); - } - }; - } - - Set plugins(); - - @SuppressWarnings("unchecked") - default Set setOf(T... items) { - Set set = new HashSet<>(); - if (items != null) { - set.addAll(Arrays.asList(items)); - } - return set; - } - - static T withConfig() { - return null; - } - - interface ModuleConfig { - NitriteModule build(); - } -} diff --git a/nitrite/src/main/java/org/dizitart/no2/repository/AnnotationScanner.java b/nitrite/src/main/java/org/dizitart/no2/repository/AnnotationScanner.java new file mode 100644 index 000000000..2fb209025 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/repository/AnnotationScanner.java @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.repository; + +import lombok.Getter; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.common.util.StringUtils; +import org.dizitart.no2.exceptions.NotIdentifiableException; +import org.dizitart.no2.repository.annotations.*; + +import java.lang.reflect.Field; +import java.util.*; + +import static org.dizitart.no2.index.IndexOptions.indexOptions; + +/** + * @author Anindya Chatterjee + */ +class AnnotationScanner { + private final Set indices; + private final Class type; + private final NitriteMapper nitriteMapper; + private final Reflector reflector; + private final NitriteCollection collection; + private final IndexValidator indexValidator; + + @Getter + private ObjectIdField objectIdField; + + public AnnotationScanner(Class type, NitriteCollection collection, NitriteMapper nitriteMapper) { + this.type = type; + this.nitriteMapper = nitriteMapper; + this.collection = collection; + this.reflector = new Reflector(); + this.indices = new HashSet<>(); + this.indexValidator = new IndexValidator(reflector); + } + + public void createIndices() { + for (Index index : indices) { + String[] fields = index.value(); + if (!collection.hasIndex(fields)) { + collection.createIndex(indexOptions(index.type()), fields); + } + } + } + + public void createIdIndex() { + if (objectIdField != null) { + String[] fieldNames = objectIdField.getFieldNames(nitriteMapper); + if (!collection.hasIndex(fieldNames)) { + collection.createIndex(fieldNames); + } + } + } + + public void scanIndices() { + // populate from @Indices + scanIndicesAnnotation(); + + // populate from @Index + scanIndexAnnotation(); + + // populate from @Entity + scanEntityAnnotation(); + + // populate from @Id + scanIdAnnotation(); + } + + private void scanIndicesAnnotation() { + List indicesList; + if (type.isAnnotationPresent(InheritIndices.class)) { + indicesList = reflector.findInheritedAnnotations(Indices.class, type); + } else { + indicesList = new ArrayList<>(); + Indices indices = type.getAnnotation(Indices.class); + if (indices != null) indicesList.add(indices); + } + + for (Indices indices : indicesList) { + Index[] indexList = indices.value(); + populateIndex(Arrays.asList(indexList)); + } + } + + private void scanIndexAnnotation() { + List indexList; + if (type.isAnnotationPresent(InheritIndices.class)) { + indexList = reflector.findInheritedAnnotations(Index.class, type); + } else { + indexList = new ArrayList<>(); + Index index = type.getAnnotation(Index.class); + if (index != null) indexList.add(index); + } + populateIndex(indexList); + } + + private void scanEntityAnnotation() { + List indexList = new ArrayList<>(); + if (type.isAnnotationPresent(InheritIndices.class)) { + List entities = reflector.findInheritedAnnotations(Entity.class, type); + if (!entities.isEmpty()) { + for (Entity entity : entities) { + indexList.addAll(Arrays.asList(entity.indices())); + } + } + } else if (type.isAnnotationPresent(Entity.class)) { + Entity entity = type.getAnnotation(Entity.class); + indexList.addAll(Arrays.asList(entity.indices())); + } + + populateIndex(indexList); + } + + private void scanIdAnnotation() { + List fieldList = reflector.getAllFields(type); + + boolean alreadyIdFound = false; + for (Field field : fieldList) { + if (field.isAnnotationPresent(Id.class)) { + Id id = field.getAnnotation(Id.class); + String fieldName = StringUtils.isNullOrEmpty(id.fieldName()) ? field.getName() : id.fieldName(); + indexValidator.validate(field.getType(), fieldName, nitriteMapper); + if (alreadyIdFound) { + throw new NotIdentifiableException("multiple id fields found for the type"); + } else { + alreadyIdFound = true; + objectIdField = new ObjectIdField(); + objectIdField.setField(field); + objectIdField.setIdFieldName(fieldName); + objectIdField.setEmbedded(isEmbeddedId(field)); + } + } + } + } + + private boolean isEmbeddedId(Field field) { + List fields = reflector.getAllFields(field.getType()); + if (fields.size() == 0) return false; + + for (Field f : fields) { + if (f.isAnnotationPresent(Embedded.class)) { + return true; + } + } + return false; + } + + private void populateIndex(List indexList) { + for (Index index : indexList) { + String[] names = index.value(); + List entityFields = new ArrayList<>(); + + for (String name : names) { + Field field = reflector.getField(type, name); + if (field != null) { + entityFields.add(field); + indexValidator.validate(field.getType(), field.getName(), nitriteMapper); + } + } + + if (entityFields.size() == names.length) { + // validation for all field are success + indices.add(index); + } + } + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/repository/Cursor.java b/nitrite/src/main/java/org/dizitart/no2/repository/Cursor.java index 06bd030c6..5d6049923 100644 --- a/nitrite/src/main/java/org/dizitart/no2/repository/Cursor.java +++ b/nitrite/src/main/java/org/dizitart/no2/repository/Cursor.java @@ -16,35 +16,32 @@ package org.dizitart.no2.repository; +import org.dizitart.no2.collection.FindPlan; import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.common.Lookup; -import org.dizitart.no2.common.NullOrder; import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.filters.Filter; - -import java.text.Collator; /** * A collection of {@link NitriteId}s of the database records, * as a result of a find operation. * * @author Anindya Chatterjee - * @see ObjectRepository#find(Filter) - * @see ObjectRepository#find() * @since 1.0 */ public interface Cursor extends RecordStream { - Cursor sort(String field, SortOrder sortOrder, Collator collator, NullOrder nullOrder); - - Cursor skipLimit(long skip, long size); + /** + * Gets a filter plan for the query. + * + * @return the filter plan + */ + FindPlan getFindPlan(); /** * Projects the result of one type into an {@link Iterable} of other type. * * @param

    the type of the target objects. * @param projectionType the projection type. - * @return `Iterable` of projected objects. + * @return java.lang.Iterable of projected objects. */

    RecordStream

    project(Class

    projectionType); @@ -52,7 +49,7 @@ public interface Cursor extends RecordStream { * Performs a left outer join with a foreign cursor with the specified lookup parameters. *

    * It performs an equality match on the localString to the foreignString from the objects of the foreign cursor. - * If an input object does not contain the localString, the join treats the field as having a value of `null` + * If an input object does not contain the localString, the join treats the field as having a value of null * for matching purposes. * * @param the type of the foreign object. @@ -64,28 +61,4 @@ public interface Cursor extends RecordStream { * @since 2.1.0 */ RecordStream join(Cursor foreignCursor, Lookup lookup, Class type); - - default Cursor sort(String field) { - return sort(field, SortOrder.Ascending); - } - - default Cursor sort(String field, SortOrder sortOrder) { - return sort(field, sortOrder, NullOrder.Default); - } - - default Cursor sort(String field, SortOrder sortOrder, Collator collator) { - return sort(field, sortOrder, collator, NullOrder.Default); - } - - default Cursor sort(String field, SortOrder sortOrder, NullOrder nullOrder) { - return sort(field, sortOrder, null, nullOrder); - } - - default Cursor skip(long skip) { - return skipLimit(skip, size()); - } - - default Cursor limit(long limit) { - return skipLimit(0, limit); - } } diff --git a/nitrite/src/main/java/org/dizitart/no2/repository/DefaultObjectRepository.java b/nitrite/src/main/java/org/dizitart/no2/repository/DefaultObjectRepository.java index 8d46de855..f6bebc643 100644 --- a/nitrite/src/main/java/org/dizitart/no2/repository/DefaultObjectRepository.java +++ b/nitrite/src/main/java/org/dizitart/no2/repository/DefaultObjectRepository.java @@ -18,14 +18,16 @@ import org.dizitart.no2.NitriteConfig; import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.FindOptions; import org.dizitart.no2.collection.NitriteCollection; import org.dizitart.no2.collection.events.CollectionEventListener; import org.dizitart.no2.collection.meta.Attributes; import org.dizitart.no2.common.WriteResult; import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexEntry; +import org.dizitart.no2.index.IndexDescriptor; import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.mapper.NitriteMapper; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.common.processors.Processor; import org.dizitart.no2.store.NitriteStore; import java.util.Collection; @@ -53,33 +55,45 @@ class DefaultObjectRepository implements ObjectRepository { } @Override - public void createIndex(String field, IndexOptions indexOptions) { - collection.createIndex(field, indexOptions); + public void addProcessor(Processor processor) { + notNull(processor, "a null processor cannot be added"); + collection.addProcessor(processor); } @Override - public void rebuildIndex(String field, boolean isAsync) { - collection.rebuildIndex(field, isAsync); + public void removeProcessor(Processor processor) { + notNull(processor, "a null processor cannot be removed"); + collection.removeProcessor(processor); } @Override - public Collection listIndices() { + public void createIndex(IndexOptions indexOptions, String... fields) { + collection.createIndex(indexOptions, fields); + } + + @Override + public void rebuildIndex(String... fields) { + collection.rebuildIndex(fields); + } + + @Override + public Collection listIndices() { return collection.listIndices(); } @Override - public boolean hasIndex(String field) { - return collection.hasIndex(field); + public boolean hasIndex(String... fields) { + return collection.hasIndex(fields); } @Override - public boolean isIndexing(String field) { - return collection.isIndexing(field); + public boolean isIndexing(String... fields) { + return collection.isIndexing(fields); } @Override - public void dropIndex(String field) { - collection.dropIndex(field); + public void dropIndex(String... fields) { + collection.dropIndex(fields); } @Override @@ -134,14 +148,10 @@ public void clear() { collection.clear(); } - @Override - public Cursor find() { - return operations.find(type); - } @Override - public Cursor find(Filter filter) { - return operations.find(filter, type); + public Cursor find(Filter filter, FindOptions findOptions) { + return operations.find(filter, findOptions, type); } @Override @@ -213,7 +223,7 @@ public NitriteCollection getDocumentCollection() { private void initialize() { NitriteMapper nitriteMapper = nitriteConfig.nitriteMapper(); operations = new RepositoryOperations(type, nitriteMapper, collection); - operations.createIndexes(); + operations.createIndices(); } } diff --git a/nitrite/src/main/java/org/dizitart/no2/repository/IndexValidator.java b/nitrite/src/main/java/org/dizitart/no2/repository/IndexValidator.java new file mode 100644 index 000000000..f18b42e03 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/repository/IndexValidator.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.repository; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.repository.annotations.Embedded; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.List; + +import static org.dizitart.no2.common.util.DocumentUtils.skeletonDocument; + +/** + * @author Anindya Chatterjee + */ +public class IndexValidator { + private final Reflector reflector; + + public IndexValidator(Reflector reflector) { + this.reflector = reflector; + } + + /** + * Validate an index field of an {@link org.dizitart.no2.repository.annotations.Entity} object. + * + * @param fieldType the field type + * @param field the field + * @param nitriteMapper the nitrite mapper + */ + public void validate(Class fieldType, String field, NitriteMapper nitriteMapper) { + if (fieldType.isPrimitive() + || fieldType == NitriteId.class + || fieldType.isInterface() + || nitriteMapper.isValueType(fieldType) + || Modifier.isAbstract(fieldType.getModifiers()) + || fieldType.isArray() + || Iterable.class.isAssignableFrom(fieldType)) { + // we will validate the solid class during insertion/update + return; + } + + Document document; + try { + document = skeletonDocument(nitriteMapper, fieldType); + if (document.size() > 0) { + // compound index + boolean embeddedFieldFound = false; + List fields = reflector.getAllFields(fieldType); + for (Field indexField : fields) { + if (indexField.isAnnotationPresent(Embedded.class)) { + embeddedFieldFound = true; + break; + } + } + + if (!embeddedFieldFound) { + throw new IndexingException("no embedded field found for object id"); + } + } else { + if (!Comparable.class.isAssignableFrom(fieldType)) { + throw new IndexingException("cannot index on non comparable field " + field); + } + } + } catch (IndexingException ie) { + throw ie; + } catch (Throwable e) { + throw new IndexingException("invalid type specified " + fieldType.getName() + " for indexing", e); + } + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/repository/MutatedObjectStream.java b/nitrite/src/main/java/org/dizitart/no2/repository/MutatedObjectStream.java index 0ef54fd66..abf3845dc 100644 --- a/nitrite/src/main/java/org/dizitart/no2/repository/MutatedObjectStream.java +++ b/nitrite/src/main/java/org/dizitart/no2/repository/MutatedObjectStream.java @@ -19,7 +19,7 @@ import org.dizitart.no2.collection.Document; import org.dizitart.no2.common.RecordStream; import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.mapper.NitriteMapper; +import org.dizitart.no2.common.mapper.NitriteMapper; import java.util.Iterator; diff --git a/nitrite/src/main/java/org/dizitart/no2/repository/ObjectCursor.java b/nitrite/src/main/java/org/dizitart/no2/repository/ObjectCursor.java index 3f13ef02c..0087a6b6c 100644 --- a/nitrite/src/main/java/org/dizitart/no2/repository/ObjectCursor.java +++ b/nitrite/src/main/java/org/dizitart/no2/repository/ObjectCursor.java @@ -18,16 +18,14 @@ import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.FindPlan; import org.dizitart.no2.common.Lookup; -import org.dizitart.no2.common.NullOrder; import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.common.SortOrder; import org.dizitart.no2.exceptions.InvalidOperationException; import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.mapper.NitriteMapper; +import org.dizitart.no2.common.mapper.NitriteMapper; import java.lang.reflect.Modifier; -import java.text.Collator; import java.util.Iterator; import static org.dizitart.no2.common.util.DocumentUtils.skeletonDocument; @@ -52,6 +50,11 @@ public long size() { return cursor.size(); } + @Override + public FindPlan getFindPlan() { + return cursor.getFindPlan(); + } + @Override public

    RecordStream

    project(Class

    projectionType) { notNull(projectionType, "projection cannot be null"); @@ -65,16 +68,6 @@ public RecordStream join(Cursor foreignCursor return new MutatedObjectStream<>(nitriteMapper, cursor.join(foreignObjectCursor.cursor, lookup), type); } - @Override - public Cursor sort(String field, SortOrder sortOrder, Collator collator, NullOrder nullOrder) { - return new ObjectCursor<>(nitriteMapper, cursor.sort(field, sortOrder, collator, nullOrder), type); - } - - @Override - public Cursor skipLimit(long skip, long size) { - return new ObjectCursor<>(nitriteMapper, cursor.skipLimit(skip, size), type); - } - @Override public Iterator iterator() { return new ObjectCursorIterator(cursor.iterator()); diff --git a/nitrite/src/main/java/org/dizitart/no2/repository/ObjectIdField.java b/nitrite/src/main/java/org/dizitart/no2/repository/ObjectIdField.java new file mode 100644 index 000000000..1061273cd --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/repository/ObjectIdField.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.repository; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.common.util.StringUtils; +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.filters.NitriteFilter; +import org.dizitart.no2.repository.annotations.Embedded; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.NavigableMap; +import java.util.TreeMap; + +import static org.dizitart.no2.filters.FluentFilter.where; + +/** + * @author Anindya Chatterjee + */ +class ObjectIdField { + private final Reflector reflector; + private final IndexValidator indexValidator; + private String[] embeddedFieldNames; + + @Getter + @Setter + private Field field; + + @Getter + @Setter + private boolean isEmbedded; + + @Getter + @Setter + private String idFieldName; + + public ObjectIdField() { + this.reflector = new Reflector(); + this.indexValidator = new IndexValidator(reflector); + } + + public String[] getFieldNames(NitriteMapper nitriteMapper) { + if (embeddedFieldNames != null) { + return embeddedFieldNames; + } + + if (!isEmbedded) { + embeddedFieldNames = new String[]{ idFieldName }; + return embeddedFieldNames; + } + + List fieldList = reflector.getAllFields(field.getType()); + NavigableMap orderedFieldName = new TreeMap<>(); + + boolean embeddedFieldFound = false; + for (Field field : fieldList) { + if (field.isAnnotationPresent(Embedded.class)) { + embeddedFieldFound = true; + Embedded embedded = field.getAnnotation(Embedded.class); + int order = embedded.order(); + String fieldName = StringUtils.isNullOrEmpty(embedded.fieldName()) + ? field.getName() : embedded.fieldName(); + + String name = this.idFieldName + NitriteConfig.getFieldSeparator() + fieldName; + indexValidator.validate(field.getType(), name, nitriteMapper); + + orderedFieldName.put(order, name); + } + } + + if (!embeddedFieldFound) { + throw new IndexingException("no embedded field found for " + field.getName()); + } + + embeddedFieldNames = orderedFieldName.values().toArray(new String[0]); + return embeddedFieldNames; + } + + public Filter createUniqueFilter(Object value, NitriteMapper nitriteMapper) { + if (embeddedFieldNames.length == 1) { + return where(idFieldName).eq(value); + } else { + Document document = nitriteMapper.convert(value, Document.class); + Filter[] filters = new Filter[embeddedFieldNames.length]; + + int index = 0; + for (String field : embeddedFieldNames) { + String docFieldName = getEmbeddedFieldName(field); + Object fieldValue = document.get(docFieldName); + filters[index++] = where(field).eq(fieldValue); + } + + NitriteFilter nitriteFilter = (NitriteFilter) Filter.and(filters); + nitriteFilter.setObjectFilter(true); + return nitriteFilter; + } + } + + private String getEmbeddedFieldName(String fieldName) { + if (fieldName.contains(NitriteConfig.getFieldSeparator())) { + return fieldName.substring(fieldName.indexOf(NitriteConfig.getFieldSeparator()) + 1); + } else { + return fieldName; + } + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/repository/ObjectRepository.java b/nitrite/src/main/java/org/dizitart/no2/repository/ObjectRepository.java index cf8062468..05efdae31 100644 --- a/nitrite/src/main/java/org/dizitart/no2/repository/ObjectRepository.java +++ b/nitrite/src/main/java/org/dizitart/no2/repository/ObjectRepository.java @@ -17,6 +17,7 @@ package org.dizitart.no2.repository; import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.FindOptions; import org.dizitart.no2.collection.NitriteCollection; import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.collection.events.CollectionEventListener; @@ -46,29 +47,25 @@ *

    * An object repository is observable like its underlying {@link NitriteCollection}. *

    - * [[app-listing]] - * [source,java] - * .Create a repository - * -- + *

    Create a repository

    + *
    + * {@code
      * // create/open a database
      * Nitrite db = Nitrite.builder()
    - * .openOrCreate("user", "password");
    - * 

    - * // create an object repository - * ObjectRepository<Employee> employeeStore = db.getRepository(Employee.class); - *

    - * // observe any change to the repository - * employeeStore.register(new ChangeListener() { + * .openOrCreate("user", "password"); * - * @param the type of the object to store. - * @author Anindya Chatterjee. + * // create an object repository + * ObjectRepository employeeStore = db.getRepository(Employee.class); * * // insert an object * Employee emp = new Employee(); * emp.setName("John Doe"); * employeeStore.insert(emp); - *

    - * -- + * } + *

    + * + * @param the type of the object to store. + * @author Anindya Chatterjee. * @see EventAware * @see Document * @see NitriteId @@ -88,16 +85,16 @@ public interface ObjectRepository extends PersistentCollection { * If any of the value is already indexed in the repository, then after insertion the * index will also be updated. *

    - * [icon="{@docRoot}/note.png"] * NOTE: This operations will notify all {@link CollectionEventListener} * instances registered to this collection with change type * {@link EventType#Insert}. + *

    * * @param object the object to insert * @param others other objects to insert in a batch. * @return the result of the write operation. - * @throws ValidationException if `object` is `null`. - * @throws InvalidIdException if the id value contains `null` value. + * @throws ValidationException if {@code object} is {@code null}. + * @throws InvalidIdException if the id value contains {@code null} value. * @throws InvalidIdException if the id value contains non comparable type, i.e. type that does not implement {@link Comparable}. * @throws InvalidIdException if the id contains value which is not of the same java type as of other objects' id in the collection. * @throws UniqueConstraintException if the value of id value clashes with the id of another object in the collection. @@ -124,26 +121,24 @@ default WriteResult insert(T object, T... others) { /** * Updates object in the repository. If the filter does not find - * any object in the collection, then the `update` object will be inserted. + * any object in the collection, then the {@code update} object will be inserted. *

    - * If the `filter` is `null`, it will update all objects in the collection. + * If the {@code filter} is {@code null}, it will update all objects in the collection. *

    - * [icon="{@docRoot}/alert.png"] - * [CAUTION] - * ==== - * If the `update` object has a non `null` value in the id value, this value + * CAUTION: + * If the {@code update} object has a non {@code null} value in the id value, this value * will be removed before update. - * ==== + *

    *

    - * [icon="{@docRoot}/note.png"] * NOTE: This operations will notify all {@link CollectionEventListener} * instances registered to this collection with change type * {@link EventType#Update}. + *

    * * @param filter the filter to apply to select objects from the collection. * @param update the modifications to apply. * @return the result of the update operation. - * @throws ValidationException if the `update` object is `null`. + * @throws ValidationException if the {@code update} object is {@code null}. */ default WriteResult update(Filter filter, T update) { return update(filter, update, false); @@ -151,95 +146,88 @@ default WriteResult update(Filter filter, T update) { /** * Updates object in the repository. Update operation can be customized - * with the help of `updateOptions`. + * with the help of {@code updateOptions}. *

    - * If the `filter` is `null`, it will update all objects in the collection unless - * `justOnce` is set to `true` in `updateOptions`. + * If the {@code filter} is {@code null}, it will update all objects in the collection unless + * {@code justOnce} is set to {@code true} in {@code updateOptions}. *

    - * [icon="{@docRoot}/alert.png"] - * [CAUTION] - * ==== - * If the `update` object has a non `null` value in the id value, this value + * CAUTION: + * If the {@code update} object has a non {@code null} value in the id value, this value * will be removed before update. - * ==== + *

    *

    - * [icon="{@docRoot}/note.png"] * NOTE: This operations will notify all {@link CollectionEventListener} * instances registered to this collection with change type - * {@link EventType#Update} or - * {@link EventType#Insert}. + * {@link EventType#Update} or {@link EventType#Insert}. + *

    * * @param filter the filter to apply to select objects from the collection. * @param update the modifications to apply. - * @param insertIfAbsent if set to `true`, `update` object will be inserted if not found. + * @param insertIfAbsent if set to {@code true}, {@code update} object will be inserted if not found. * @return the result of the update operation. - * @throws ValidationException if the `update` object is `null`. - * @throws ValidationException if `updateOptions` is `null`. + * @throws ValidationException if the {@code update} object is {@code null}. + * @throws ValidationException if {@code updateOptions} is {@code null}. */ WriteResult update(Filter filter, T update, boolean insertIfAbsent); /** - * Updates object in the repository by setting the field specified in `document`. + * Updates object in the repository by setting the field specified in {@code document}. *

    - * If the `filter` is `null`, it will update all objects in the collection. + * If the {@code filter} is {@code null}, it will update all objects in the collection. *

    - * [icon="{@docRoot}/alert.png"] - * [CAUTION] - * ==== - * The `update` document should not contain `_id` field. - * ==== + * CAUTION: + * The {@code update} document should not contain {@code _id} field. + *

    *

    - * [icon="{@docRoot}/note.png"] * NOTE: This operations will notify all {@link CollectionEventListener} * instances registered to this collection with change type * {@link EventType#Update}. + *

    * * @param filter the filter to apply to select objects from the collection. * @param update the modifications to apply. * @return the result of the update operation. - * @throws ValidationException if the `update` object is `null`. + * @throws ValidationException if the {@code update} object is {@code null}. */ default WriteResult update(Filter filter, Document update) { return update(filter, update, false); } /** - * Updates object in the repository by setting the field specified in `document`. + * Updates object in the repository by setting the field specified in {@code document}. * Update operation can either update the first matching object or all matching - * objects depending on the value of `justOnce`. + * objects depending on the value of {@code justOnce}. *

    - * If the `filter` is `null`, it will update all objects in the collection unless - * `justOnce` is set to `true`. + * If the {@code filter} is {@code null}, it will update all objects in the collection unless + * {@code justOnce} is set to {@code true}. *

    - * [icon="{@docRoot}/alert.png"] - * [CAUTION] - * ==== - * The `update` document should not contain `_id` field. - * ==== + * CAUTION: + * The {@code update} document should not contain {@code _id} field. + *

    *

    - * [icon="{@docRoot}/note.png"] * NOTE: This operations will notify all {@link CollectionEventListener} * instances registered to this collection with change type * {@link EventType#Update}. - * + *

    + * * @param filter the filter to apply to select objects from the collection. * @param update the modifications to apply. * @param justOnce indicates if update should be applied on first matching object or all. * @return the result of the update operation. - * @throws ValidationException if the `update` object is `null`. + * @throws ValidationException if the {@code update} object is {@code null}. */ WriteResult update(Filter filter, Document update, boolean justOnce); /** * Removes matching elements from the collection. *

    - * If the `filter` is `null`, it will remove all objects from the collection. + * If the {@code filter} is {@code null}, it will remove all objects from the collection. *

    - * [icon="{@docRoot}/note.png"] * NOTE: This operations will notify all {@link CollectionEventListener} * instances registered to this collection with change type * {@link EventType#Remove}. - * + *

    + * * @param filter the filter to apply to select elements from collection. * @return the result of the remove operation. */ @@ -249,16 +237,16 @@ default WriteResult remove(Filter filter) { /** * Removes object from the collection. Remove operation can be customized by - * `removeOptions`. + * {@code removeOptions}. *

    - * If the `filter` is `null`, it will remove all objects in the collection unless - * `justOnce` is set to `true` in `removeOptions`. + * If the {@code filter} is {@code null}, it will remove all objects in the collection unless + * {@code justOnce} is set to {@code true} in {@code removeOptions}. *

    - * [icon="{@docRoot}/note.png"] * NOTE: This operations will notify all {@link CollectionEventListener} * instances registered to this collection with change type * {@link EventType#Remove}. - * + *

    + * * @param filter the filter to apply to select objects from collection. * @param justOne indicates if only one element will be removed or all of them. * @return the result of the remove operation. @@ -270,7 +258,9 @@ default WriteResult remove(Filter filter) { * * @return a cursor to all objects in the collection. */ - Cursor find(); + default Cursor find() { + return find(Filter.ALL, null); + } /** * Applies a filter on the collection and returns a cursor to the @@ -278,28 +268,54 @@ default WriteResult remove(Filter filter) { *

    * See {@link Filter} for all available filters. *

    - * [icon="{@docRoot}/note.png"] * NOTE: If there is an index on the value specified in the filter, this operation * will take advantage of the index. + *

    * * @param filter the filter to apply to select objects from collection. * @return a cursor to all selected objects. - * @throws ValidationException if `filter` is null. * @see Filter * @see Cursor#project(Class) */ - Cursor find(Filter filter); + default Cursor find(Filter filter) { + return find(filter, null); + } + + /** + * Returns a customized cursor to all objects in the collection. + * + * @param findOptions specifies pagination, sort options for the cursor. + * @return a cursor to all selected objects. + */ + default Cursor find(FindOptions findOptions) { + return find(Filter.ALL, findOptions); + } + + /** + * Applies a filter on the collection and returns a customized cursor to the + * selected objects. + * + *

    + * NOTE: If there is an index on the value specified in the filter, this operation + * will take advantage of the index. + *

    + * + * @param filter the filter to apply to select objects from collection. + * @param findOptions specifies pagination, sort options for the cursor. + * @return a cursor to all selected objects. + */ + Cursor find(Filter filter, FindOptions findOptions); /** * Gets a single element from the repository by its id. If no element - * is found, it will return `null`. The object must have a field annotated with {@link Id}, + * is found, it will return {@code null}. The object must have a field annotated with {@link Id}, * otherwise this call will throw {@link InvalidIdException}. * * @param the type parameter * @param id the id value * @return the unique object associated with the id. - * @throws ValidationException if `id` is `null`. - * @throws InvalidIdException if the id value is `null`, or the type is not compatible. + * @throws ValidationException if id is {@code null}. + * @throws InvalidIdException if the id value is {@code null}, or the type is not compatible. * @throws NotIdentifiableException if the object has no field marked with {@link Id}. */ T getById(I id); diff --git a/nitrite/src/main/java/org/dizitart/no2/repository/Reflector.java b/nitrite/src/main/java/org/dizitart/no2/repository/Reflector.java new file mode 100644 index 000000000..b229cfeca --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/repository/Reflector.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.repository; + +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.repository.annotations.InheritIndices; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import static org.dizitart.no2.common.util.StringUtils.isNullOrEmpty; +import static org.dizitart.no2.common.util.ValidationUtils.notNull; + +/** + * @author Anindya Chatterjee + */ +class Reflector { + @SuppressWarnings("rawtypes") + public List findInheritedAnnotations(Class annotation, Class type) { + notNull(type, "type cannot be null"); + notNull(annotation, "annotationClass cannot be null"); + List annotations = new ArrayList<>(); + + T t = type.getAnnotation(annotation); + if (t != null) annotations.add(t); + + Class[] interfaces = type.getInterfaces(); + for (Class anInterface : interfaces) { + T ann = anInterface.getAnnotation(annotation); + if (ann != null) annotations.add(ann); + } + + Class parentClass = type.getSuperclass(); + if (parentClass != null && !parentClass.equals(Object.class)) { + List list = findInheritedAnnotations(annotation, parentClass); + annotations.addAll(list); + } + + return annotations; + } + + public Field getEmbeddedField(Class startingClass, String embeddedField) { + String regex = MessageFormat.format("\\{0}", NitriteConfig.getFieldSeparator()); + String[] split = embeddedField.split(regex, 2); + String key = split[0]; + String remaining = split.length == 2 ? split[1] : ""; + + if (isNullOrEmpty(key)) { + throw new ValidationException("invalid embedded field provided"); + } + + Field field; + try { + field = startingClass.getDeclaredField(key); + } catch (NoSuchFieldException e) { + throw new ValidationException("no such field '" + key + "' for type " + startingClass.getName(), e); + } + + if (!isNullOrEmpty(remaining) || remaining.contains(NitriteConfig.getFieldSeparator())) { + return getEmbeddedField(field.getType(), remaining); + } else { + return field; + } + } + + public List getFieldsUpto(Class startClass, Class exclusiveParent) { + notNull(startClass, "startClass cannot be null"); + List currentClassFields = new ArrayList<>(Arrays.asList(startClass.getDeclaredFields())); + filterSynthetics(currentClassFields); + Class parentClass = startClass.getSuperclass(); + + if (parentClass != null && !(parentClass.equals(exclusiveParent))) { + List parentClassFields = getFieldsUpto(parentClass, exclusiveParent); + currentClassFields.addAll(parentClassFields); + } + + return currentClassFields; + } + + public Field getField(Class type, String name) { + if (name.contains(NitriteConfig.getFieldSeparator())) { + return getEmbeddedField(type, name); + } else { + // first check declared fields (fix for kotlin properties, ref: issue #54) + // if nothing found and is-recursive then check recursively + Field[] declaredFields = type.getDeclaredFields(); + Field field = null; + for (Field declaredField : declaredFields) { + if (declaredField.getName().equals(name)) { + field = declaredField; + break; + } + } + + if (field == null) { + List fields = getFieldsUpto(type, Object.class); + for (Field recursiveField : fields) { + if (recursiveField.getName().equals(name)) { + field = recursiveField; + break; + } + } + } + if (field == null) { + throw new ValidationException("no such field '" + name + "' for type " + type.getName()); + } + return field; + } + } + + public List getAllFields(Class type) { + List fields; + if (type.isAnnotationPresent(InheritIndices.class)) { + fields = getFieldsUpto(type, Object.class); + } else { + fields = Arrays.asList(type.getDeclaredFields()); + } + return fields; + } + + public void filterSynthetics(List fields) { + if (fields == null || fields.isEmpty()) return; + Iterator iterator = fields.iterator(); + if (iterator.hasNext()) { + do { + Field f = iterator.next(); + if (f.isSynthetic()) iterator.remove(); + } while (iterator.hasNext()); + } + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/repository/RepositoryFactory.java b/nitrite/src/main/java/org/dizitart/no2/repository/RepositoryFactory.java index 1a928a2c1..2fe8de751 100644 --- a/nitrite/src/main/java/org/dizitart/no2/repository/RepositoryFactory.java +++ b/nitrite/src/main/java/org/dizitart/no2/repository/RepositoryFactory.java @@ -18,39 +18,63 @@ import org.dizitart.no2.NitriteConfig; import org.dizitart.no2.collection.CollectionFactory; -import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.NitriteCollection; import org.dizitart.no2.common.util.StringUtils; +import org.dizitart.no2.exceptions.NitriteIOException; import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.common.mapper.NitriteMapper; import org.dizitart.no2.store.NitriteStore; +import org.dizitart.no2.store.StoreCatalog; import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.ReentrantLock; -import static org.dizitart.no2.common.Constants.*; import static org.dizitart.no2.common.util.ObjectUtils.findRepositoryName; /** + * The {@link ObjectRepository} factory. + * * @author Anindya Chatterjee + * @since 1.0 */ public class RepositoryFactory { private final Map> repositoryMap; private final CollectionFactory collectionFactory; private final ReentrantLock lock; + /** + * Instantiates a new {@link RepositoryFactory}. + * + * @param collectionFactory the collection factory + */ public RepositoryFactory(CollectionFactory collectionFactory) { this.collectionFactory = collectionFactory; this.repositoryMap = new HashMap<>(); this.lock = new ReentrantLock(); } + /** + * Gets an {@link ObjectRepository} by type. + * + * @param the type parameter + * @param nitriteConfig the nitrite config + * @param type the type + * @return the repository + */ public ObjectRepository getRepository(NitriteConfig nitriteConfig, Class type) { return getRepository(nitriteConfig, type, null); } + /** + * Gets an {@link ObjectRepository} by type and a key. + * + * @param the type parameter + * @param nitriteConfig the nitrite config + * @param type the type + * @param key the key + * @return the repository + */ @SuppressWarnings("unchecked") public ObjectRepository getRepository(NitriteConfig nitriteConfig, Class type, String key) { if (type == null) { @@ -81,6 +105,9 @@ public ObjectRepository getRepository(NitriteConfig nitriteConfig, Class< } } + /** + * Closes all opened {@link ObjectRepository}s and clear internal data from this class. + */ public void clear() { try { lock.lock(); @@ -88,6 +115,8 @@ public void clear() { repository.close(); } repositoryMap.clear(); + } catch (Exception e) { + throw new NitriteIOException("failed to close an object repository", e); } finally { lock.unlock(); } @@ -115,16 +144,11 @@ private ObjectRepository createRepository(NitriteConfig nitriteConfig, Cl } private void writeCatalog(NitriteStore store, String name, String key) { - NitriteMap catalogMap = store.openMap(COLLECTION_CATALOG, String.class, Document.class); - Document document = StringUtils.isNullOrEmpty(key) ? catalogMap.get(TAG_REPOSITORIES) - : catalogMap.get(TAG_KEYED_REPOSITORIES); - if (document == null) document = Document.createDocument(); - - document.put(name, true); + StoreCatalog storeCatalog = store.getCatalog(); if (StringUtils.isNullOrEmpty(key)) { - catalogMap.put(TAG_REPOSITORIES, document); + storeCatalog.writeRepositoryEntry(name); } else { - catalogMap.put(TAG_KEYED_REPOSITORIES, document); + storeCatalog.writeKeyedRepositoryEntries(name); } } } diff --git a/nitrite/src/main/java/org/dizitart/no2/repository/RepositoryOperations.java b/nitrite/src/main/java/org/dizitart/no2/repository/RepositoryOperations.java index fcada797a..eb4e2703b 100644 --- a/nitrite/src/main/java/org/dizitart/no2/repository/RepositoryOperations.java +++ b/nitrite/src/main/java/org/dizitart/no2/repository/RepositoryOperations.java @@ -16,68 +16,69 @@ package org.dizitart.no2.repository; -import org.dizitart.no2.NitriteConfig; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.collection.*; +import org.dizitart.no2.common.mapper.NitriteMapper; import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.exceptions.*; +import org.dizitart.no2.exceptions.InvalidIdException; +import org.dizitart.no2.exceptions.NotIdentifiableException; +import org.dizitart.no2.exceptions.ValidationException; import org.dizitart.no2.filters.Filter; import org.dizitart.no2.filters.NitriteFilter; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.*; -import java.lang.annotation.Annotation; import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.text.MessageFormat; -import java.util.*; import static org.dizitart.no2.common.Constants.DOC_ID; -import static org.dizitart.no2.common.util.DocumentUtils.skeletonDocument; import static org.dizitart.no2.common.util.ObjectUtils.isCompatibleTypes; import static org.dizitart.no2.common.util.StringUtils.isNullOrEmpty; -import static org.dizitart.no2.common.util.ValidationUtils.notNull; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; /** + * The {@link ObjectRepository} operations. + *

    + * This class is for internal use only. + *

    + * * @author Anindya Chatterjee + * @since 4.0 */ public class RepositoryOperations { private final NitriteMapper nitriteMapper; private final Class type; private final NitriteCollection collection; - private Field idField; - + private final AnnotationScanner annotationScanner; + private ObjectIdField objectIdField; + + /** + * Instantiates a new {@link RepositoryOperations}. + * + * @param type the type + * @param nitriteMapper the nitrite mapper + * @param collection the collection + */ public RepositoryOperations(Class type, NitriteMapper nitriteMapper, NitriteCollection collection) { this.type = type; this.nitriteMapper = nitriteMapper; this.collection = collection; + this.annotationScanner = new AnnotationScanner(type, collection, nitriteMapper); validateCollection(); } - public void createIndexes() { - Set indexes = extractIndices(type); - for (Index idx : indexes) { - String field = idx.value(); - if (!collection.hasIndex(field)) { - collection.createIndex(idx.value(), indexOptions(idx.type(), false)); - } - } - - idField = getIdField(type); - if (idField != null) { - String field = idField.getName(); - if (!collection.hasIndex(field)) { - collection.createIndex(field, indexOptions(IndexType.Unique)); - } - } + /** + * Create indices. + */ + public void createIndices() { + annotationScanner.scanIndices(); + annotationScanner.createIndices(); + annotationScanner.createIdIndex(); + objectIdField = annotationScanner.getObjectIdField(); } + /** + * Serialize fields. + * + * @param document the document + */ public void serializeFields(Document document) { if (document != null) { for (Pair pair : document) { @@ -90,6 +91,13 @@ public void serializeFields(Document document) { } } + /** + * To documents document [ ]. + * + * @param the type parameter + * @param others the others + * @return the document [ ] + */ public Document[] toDocuments(T[] others) { if (others == null || others.length == 0) return null; Document[] documents = new Document[others.length]; @@ -99,16 +107,27 @@ public Document[] toDocuments(T[] others) { return documents; } + /** + * To document document. + * + * @param the type parameter + * @param object the object + * @param update the update + * @return the document + */ public Document toDocument(T object, boolean update) { Document document = nitriteMapper.convert(object, Document.class); - if (idField != null) { + + if (objectIdField != null) { + Field idField = objectIdField.getField(); + if (idField.getType() == NitriteId.class) { try { idField.setAccessible(true); if (idField.get(object) == null) { NitriteId id = document.getId(); idField.set(object, id); - document.put(idField.getName(), nitriteMapper.convert(id, Comparable.class)); + document.put(objectIdField.getIdFieldName(), nitriteMapper.convert(id, Comparable.class)); } else if (!update) { throw new InvalidIdException("auto generated id should not be set manually"); } @@ -116,7 +135,8 @@ public Document toDocument(T object, boolean update) { throw new InvalidIdException("auto generated id value cannot be accessed"); } } - Object idValue = document.get(idField.getName()); + + Object idValue = document.get(objectIdField.getIdFieldName()); if (idValue == null) { throw new InvalidIdException("id cannot be null"); } @@ -127,47 +147,74 @@ public Document toDocument(T object, boolean update) { return document; } + /** + * Create unique filter filter. + * + * @param object the object + * @return the filter + */ public Filter createUniqueFilter(Object object) { - if (idField == null) { + if (objectIdField == null) { throw new NotIdentifiableException("update operation failed as no id value found for the object"); } + Field idField = objectIdField.getField(); idField.setAccessible(true); try { Object value = idField.get(object); if (value == null) { throw new InvalidIdException("id value cannot be null"); } - return where(idField.getName()).eq(value); + return objectIdField.createUniqueFilter(value, nitriteMapper); } catch (IllegalAccessException iae) { throw new InvalidIdException("id field is not accessible"); } } + /** + * Remove nitrite id. + * + * @param document the document + */ public void removeNitriteId(Document document) { document.remove(DOC_ID); - if (idField != null && idField.getType() == NitriteId.class) { - document.remove(idField.getName()); + if (objectIdField != null) { + Field idField = objectIdField.getField(); + if (idField != null && !objectIdField.isEmbedded() + && idField.getType() == NitriteId.class) { + document.remove(idField.getName()); + } } } + /** + * Create id filter filter. + * + * @param the type parameter + * @param id the id + * @return the filter + */ public Filter createIdFilter(I id) { - if (idField != null) { + if (objectIdField != null) { if (id == null) { throw new InvalidIdException("a null id is not a valid id"); } - - if (isCompatibleTypes(idField.getType(), id.getClass())) { - return where(idField.getName()).eq(id); - } else { - throw new InvalidIdException(id.getClass().getName() + " is not assignable to id type " - + idField.getType().getName()); + if (!isCompatibleTypes(id.getClass(), objectIdField.getField().getType())) { + throw new InvalidIdException("a value of invalid type is provided as id"); } + + return objectIdField.createUniqueFilter(id, nitriteMapper); } else { throw new NotIdentifiableException(type.getName() + " does not have any id field"); } } + /** + * As object filter filter. + * + * @param filter the filter + * @return the filter + */ public Filter asObjectFilter(Filter filter) { if (filter instanceof NitriteFilter) { NitriteFilter nitriteFilter = (NitriteFilter) filter; @@ -177,131 +224,18 @@ public Filter asObjectFilter(Filter filter) { return filter; } - Field getIdField(Class type) { - List fields; - if (type.isAnnotationPresent(InheritIndices.class)) { - fields = getFieldsUpto(type, Object.class); - } else { - fields = Arrays.asList(type.getDeclaredFields()); - } - - boolean alreadyIdFound = false; - Field idField = null; - for (Field field : fields) { - if (field.isAnnotationPresent(Id.class)) { - validateObjectIndexField(nitriteMapper, field.getType(), field.getName()); - if (alreadyIdFound) { - throw new NotIdentifiableException("multiple id fields found for the type"); - } else { - alreadyIdFound = true; - idField = field; - } - } - } - return idField; - } - - Set extractIndices(Class type) { - notNull(type, "type cannot be null"); - - // populate from @Indices - List indicesList; - if (type.isAnnotationPresent(InheritIndices.class)) { - indicesList = findAnnotations(Indices.class, type); - } else { - indicesList = new ArrayList<>(); - Indices indices = type.getAnnotation(Indices.class); - if (indices != null) indicesList.add(indices); - } - - Set indexSet = new LinkedHashSet<>(); - for (Indices indices : indicesList) { - Index[] indexList = indices.value(); - populateIndex(nitriteMapper, type, Arrays.asList(indexList), indexSet); - } - - // populate from @Index - List indexList; - if (type.isAnnotationPresent(InheritIndices.class)) { - indexList = findAnnotations(Index.class, type); - } else { - indexList = new ArrayList<>(); - Index index = type.getAnnotation(Index.class); - if (index != null) indexList.add(index); - } - - // populate from @Entity - if (type.isAnnotationPresent(InheritIndices.class)) { - List entities = findAnnotations(Entity.class, type); - if (!entities.isEmpty()) { - for (Entity entity : entities) { - indexList.addAll(Arrays.asList(entity.indices())); - } - } - } else if (type.isAnnotationPresent(Entity.class)) { - Entity entity = type.getAnnotation(Entity.class); - indexList.addAll(Arrays.asList(entity.indices())); - } - - populateIndex(nitriteMapper, type, indexList, indexSet); - - return indexSet; - } - - Field getField(Class type, String name) { - if (name.contains(NitriteConfig.getFieldSeparator())) { - return getEmbeddedField(type, name); - } else { - // first check declared fields (fix for kotlin properties, ref: issue #54) - // if nothing found and is-recursive then check recursively - Field[] declaredFields = type.getDeclaredFields(); - Field field = null; - for (Field declaredField : declaredFields) { - if (declaredField.getName().equals(name)) { - field = declaredField; - break; - } - } - - if (field == null) { - List fields = getFieldsUpto(type, Object.class); - for (Field recursiveField : fields) { - if (recursiveField.getName().equals(name)) { - field = recursiveField; - break; - } - } - } - if (field == null) { - throw new ValidationException("no such field '" + name + "' for type " + type.getName()); - } - return field; - } - } - - List getFieldsUpto(Class startClass, Class exclusiveParent) { - notNull(startClass, "startClass cannot be null"); - List currentClassFields = new ArrayList<>(Arrays.asList(startClass.getDeclaredFields())); - filterSynthetics(currentClassFields); - Class parentClass = startClass.getSuperclass(); - - if (parentClass != null && !(parentClass.equals(exclusiveParent))) { - List parentClassFields = getFieldsUpto(parentClass, exclusiveParent); - currentClassFields.addAll(parentClassFields); - } - - return currentClassFields; - } - - private static void filterSynthetics(List fields) { - if (fields == null || fields.isEmpty()) return; - Iterator iterator = fields.iterator(); - if (iterator.hasNext()) { - do { - Field f = iterator.next(); - if (f.isSynthetic()) iterator.remove(); - } while (iterator.hasNext()); - } + /** + * Find cursor. + * + * @param the type parameter + * @param filter the filter + * @param findOptions the find options + * @param type the type + * @return the cursor + */ + public Cursor find(Filter filter, FindOptions findOptions, Class type) { + DocumentCursor documentCursor = collection.find(asObjectFilter(filter), findOptions); + return new ObjectCursor<>(nitriteMapper, documentCursor, type); } private void validateCollection() { @@ -309,103 +243,4 @@ private void validateCollection() { throw new ValidationException("repository has not been initialized properly"); } } - - private Field getEmbeddedField(Class startingClass, String embeddedField) { - String regex = MessageFormat.format("\\{0}", NitriteConfig.getFieldSeparator()); - String[] split = embeddedField.split(regex, 2); - String key = split[0]; - String remaining = split.length == 2 ? split[1] : ""; - - if (isNullOrEmpty(key)) { - throw new ValidationException("invalid embedded field provided"); - } - - Field field; - try { - field = startingClass.getDeclaredField(key); - } catch (NoSuchFieldException e) { - throw new ValidationException("no such field '" + key + "' for type " + startingClass.getName(), e); - } - - if (!isNullOrEmpty(remaining) || remaining.contains(NitriteConfig.getFieldSeparator())) { - return getEmbeddedField(field.getType(), remaining); - } else { - return field; - } - } - - private void populateIndex(NitriteMapper nitriteMapper, Class type, - List indexList, Set indexSet) { - for (Index index : indexList) { - String name = index.value(); - Field field = getField(type, name); - if (field != null) { - validateObjectIndexField(nitriteMapper, field.getType(), field.getName()); - indexSet.add(index); - } - } - } - - private void validateObjectIndexField(NitriteMapper nitriteMapper, Class fieldType, String field) { - if (!Comparable.class.isAssignableFrom(fieldType) && !fieldType.isPrimitive()) { - throw new IndexingException("cannot index on non comparable field " + field); - } - - if (Iterable.class.isAssignableFrom(fieldType) || fieldType.isArray()) { - throw new IndexingException("indexing on arrays or collections for field " + field - + " are not supported"); - } - - if (fieldType.isPrimitive() - || fieldType == NitriteId.class - || fieldType.isInterface() - || nitriteMapper.isValueType(fieldType) - || Modifier.isAbstract(fieldType.getModifiers())) { - // we will validate the solid class during insertion/update - return; - } - - Document document; - try { - document = skeletonDocument(nitriteMapper, fieldType); - } catch (Throwable e) { - throw new IndexingException("invalid type specified " + fieldType.getName() + " for indexing", e); - } - - if (document == null || document.size() > 0) { - throw new InvalidOperationException("compound index on field " + field + " is not supported"); - } - } - - @SuppressWarnings("rawtypes") - private List findAnnotations(Class annotation, Class type) { - notNull(type, "type cannot be null"); - notNull(annotation, "annotationClass cannot be null"); - List annotations = new ArrayList<>(); - - T t = type.getAnnotation(annotation); - if (t != null) annotations.add(t); - - Class[] interfaces = type.getInterfaces(); - for (Class anInterface : interfaces) { - T ann = anInterface.getAnnotation(annotation); - if (ann != null) annotations.add(ann); - } - - Class parentClass = type.getSuperclass(); - if (parentClass != null && !parentClass.equals(Object.class)) { - List list = findAnnotations(annotation, parentClass); - annotations.addAll(list); - } - - return annotations; - } - - public Cursor find(Class type) { - return new ObjectCursor<>(nitriteMapper, collection.find(), type); - } - - public Cursor find(Filter filter, Class type) { - return new ObjectCursor<>(nitriteMapper, collection.find(asObjectFilter(filter)), type); - } } diff --git a/nitrite/src/main/java/org/dizitart/no2/repository/annotations/Embedded.java b/nitrite/src/main/java/org/dizitart/no2/repository/annotations/Embedded.java new file mode 100644 index 000000000..6e4240006 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/repository/annotations/Embedded.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.repository.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Anindya Chatterjee + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Embedded { + int order(); + String fieldName() default ""; +} diff --git a/nitrite/src/main/java/org/dizitart/no2/repository/annotations/Entity.java b/nitrite/src/main/java/org/dizitart/no2/repository/annotations/Entity.java index 0a618ecf9..92822a3d2 100644 --- a/nitrite/src/main/java/org/dizitart/no2/repository/annotations/Entity.java +++ b/nitrite/src/main/java/org/dizitart/no2/repository/annotations/Entity.java @@ -22,11 +22,26 @@ import java.lang.annotation.Target; /** + * Represents an entity for an {@link org.dizitart.no2.repository.ObjectRepository}. + * * @author Anindya Chatterjee + * @since 4.0 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Entity { + /** + * Name of the {@link org.dizitart.no2.repository.ObjectRepository}. By default, + * the name would be the class name of the entity. + * + * @return the name + */ String value() default ""; + + /** + * Index definitions of the entity. + * + * @return the index definitions + */ Index[] indices() default {}; } diff --git a/nitrite/src/main/java/org/dizitart/no2/repository/annotations/Id.java b/nitrite/src/main/java/org/dizitart/no2/repository/annotations/Id.java index a886b94a4..d63c53729 100644 --- a/nitrite/src/main/java/org/dizitart/no2/repository/annotations/Id.java +++ b/nitrite/src/main/java/org/dizitart/no2/repository/annotations/Id.java @@ -30,4 +30,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Id { + String fieldName() default ""; } diff --git a/nitrite/src/main/java/org/dizitart/no2/repository/annotations/Index.java b/nitrite/src/main/java/org/dizitart/no2/repository/annotations/Index.java index 150a9b34f..635e5fd33 100644 --- a/nitrite/src/main/java/org/dizitart/no2/repository/annotations/Index.java +++ b/nitrite/src/main/java/org/dizitart/no2/repository/annotations/Index.java @@ -16,22 +16,14 @@ package org.dizitart.no2.repository.annotations; -import org.dizitart.no2.index.IndexOptions; import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.repository.ObjectRepository; import java.lang.annotation.*; /** * Specifies a field to be indexed. - *

    - * [[app-listing]] - * [source,java] - * .Example of Index annotation - * -- * * @author Anindya Chatterjee. - * @see ObjectRepository#createIndex(String, IndexOptions) * @since 1.0 */ @Retention(RetentionPolicy.RUNTIME) @@ -43,12 +35,12 @@ * * @return the field name */ - String value(); + String[] value(); /** * Type of the index. * * @return the index type */ - String type() default IndexType.Unique; + String type() default IndexType.UNIQUE; } diff --git a/nitrite/src/main/java/org/dizitart/no2/repository/annotations/Indices.java b/nitrite/src/main/java/org/dizitart/no2/repository/annotations/Indices.java index e43626523..836fc5a93 100644 --- a/nitrite/src/main/java/org/dizitart/no2/repository/annotations/Indices.java +++ b/nitrite/src/main/java/org/dizitart/no2/repository/annotations/Indices.java @@ -23,15 +23,8 @@ /** * Specifies multiple indexed fields for a class. - *

    - * [[app-listing]] - * [source,java] - * .Example of Indices annotation - * -- - * + * @author Anindya Chatterjee. - * - * * @see Index * @since 1.0 */ diff --git a/nitrite/src/main/java/org/dizitart/no2/repository/annotations/InheritIndices.java b/nitrite/src/main/java/org/dizitart/no2/repository/annotations/InheritIndices.java index 405f0b5ac..119e7303a 100644 --- a/nitrite/src/main/java/org/dizitart/no2/repository/annotations/InheritIndices.java +++ b/nitrite/src/main/java/org/dizitart/no2/repository/annotations/InheritIndices.java @@ -20,7 +20,8 @@ /** * Indicates that a class should consider all index related - * annotations - `@Id`, `@Index`, `@Indices` from its superclass. + * annotations - @Id, @Index, + * @Indices from its superclass. * * @author Anindya Chatterjee * @since 2.1.0 diff --git a/nitrite/src/main/java/org/dizitart/no2/store/AbstractNitriteStore.java b/nitrite/src/main/java/org/dizitart/no2/store/AbstractNitriteStore.java index d6928e34b..87a4f084b 100644 --- a/nitrite/src/main/java/org/dizitart/no2/store/AbstractNitriteStore.java +++ b/nitrite/src/main/java/org/dizitart/no2/store/AbstractNitriteStore.java @@ -4,22 +4,22 @@ import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.dizitart.no2.NitriteConfig; -import org.dizitart.no2.collection.Document; import org.dizitart.no2.common.event.NitriteEventBus; import org.dizitart.no2.store.events.EventInfo; import org.dizitart.no2.store.events.StoreEventBus; import org.dizitart.no2.store.events.StoreEventListener; import org.dizitart.no2.store.events.StoreEvents; -import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import java.util.Set; -import static org.dizitart.no2.common.Constants.*; -import static org.dizitart.no2.common.util.ObjectUtils.getKeyName; -import static org.dizitart.no2.common.util.ObjectUtils.getKeyedRepositoryType; - +/** + * An abstract {@link NitriteStore} implementation. + * + * @param the type parameter + * @author Anindya Chatterjee + * @since 4.0 + */ @Slf4j public abstract class AbstractNitriteStore implements NitriteStore { @@ -27,13 +27,30 @@ public abstract class AbstractNitriteStore @Getter @Setter private Config storeConfig; + /** + * The {@link NitriteEventBus} for the database. + */ protected final NitriteEventBus eventBus; + + /** + * The {@link NitriteConfig} for this store. + */ protected NitriteConfig nitriteConfig; + private StoreCatalog storeCatalog; + + /** + * Instantiates a new {@link AbstractNitriteStore}. + */ protected AbstractNitriteStore() { eventBus = new StoreEventBus(); } + /** + * Alerts about an {@link StoreEvents} to all subscribed {@link StoreEventListener}s. + * + * @param eventType the event type + */ protected void alert(StoreEvents eventType) { EventInfo event = new EventInfo(eventType, nitriteConfig); eventBus.post(event); @@ -41,43 +58,17 @@ protected void alert(StoreEvents eventType) { @Override public Set getCollectionNames() { - NitriteMap catalogMap = openMap(COLLECTION_CATALOG, String.class, Document.class); - Document document = catalogMap.get(TAG_COLLECTIONS); - if (document == null) return new HashSet<>(); - - return document.getFields(); + return getCatalog().getCollectionNames(); } @Override public Set getRepositoryRegistry() { - NitriteMap catalogMap = openMap(COLLECTION_CATALOG, String.class, Document.class); - Document document = catalogMap.get(TAG_REPOSITORIES); - if (document == null) return new HashSet<>(); - - return document.getFields(); + return getCatalog().getRepositoryNames(); } @Override public Map> getKeyedRepositoryRegistry() { - NitriteMap catalogMap = openMap(COLLECTION_CATALOG, String.class, Document.class); - Document document = catalogMap.get(TAG_KEYED_REPOSITORIES); - if (document == null) return new HashMap<>(); - - Map> resultMap = new HashMap<>(); - for (String field : document.getFields()) { - String key = getKeyName(field); - String type = getKeyedRepositoryType(field); - - Set types; - if (resultMap.containsKey(key)) { - types = resultMap.get(key); - } else { - types = new HashSet<>(); - } - types.add(type); - resultMap.put(key, types); - } - return resultMap; + return getCatalog().getKeyedRepositoryNames(); } @Override @@ -85,11 +76,6 @@ public void beforeClose() { alert(StoreEvents.Closing); } - @Override - public IndexCatalog getIndexCatalog() { - return new IndexCatalog(this); - } - @Override public void removeRTree(String mapName) { this.removeMap(mapName); @@ -109,4 +95,12 @@ public void unsubscribe(StoreEventListener listener) { public void initialize(NitriteConfig nitriteConfig) { this.nitriteConfig = nitriteConfig; } + + @Override + public StoreCatalog getCatalog() { + if (storeCatalog == null) { + this.storeCatalog = new StoreCatalog(this); + } + return storeCatalog; + } } diff --git a/nitrite/src/main/java/org/dizitart/no2/store/DatabaseMetaData.java b/nitrite/src/main/java/org/dizitart/no2/store/DatabaseMetaData.java deleted file mode 100644 index 4a0cf6647..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/store/DatabaseMetaData.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.store; - -import lombok.Data; -import lombok.NoArgsConstructor; -import org.dizitart.no2.collection.Document; - -/** - * @author Anindya Chatterjee. - */ -@Data -@NoArgsConstructor -public class DatabaseMetaData { - private Long createTime; - private String storeVersion; - private String nitriteVersion; - private Integer schemaVersion; - - public DatabaseMetaData(Document document) { - populateInfo(document); - } - - public Document getInfo() { - return Document.createDocument() - .put("createTime", createTime) - .put("storeVersion", storeVersion) - .put("nitriteVersion", nitriteVersion) - .put("schemaVersion", schemaVersion); - } - - private void populateInfo(Document document) { - createTime = document.get("createTime", Long.class); - storeVersion = document.get("storeVersion", String.class); - nitriteVersion = document.get("nitriteVersion", String.class); - schemaVersion = document.get("schemaVersion", Integer.class); - } -} diff --git a/nitrite/src/main/java/org/dizitart/no2/store/IndexCatalog.java b/nitrite/src/main/java/org/dizitart/no2/store/IndexCatalog.java deleted file mode 100644 index 24eae380b..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/store/IndexCatalog.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.store; - -import org.dizitart.no2.index.IndexEntry; -import org.dizitart.no2.index.IndexMeta; - -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; - -import static org.dizitart.no2.common.Constants.*; - -/** - * - * @since 4.0 - * @author Anindya Chatterjee - */ -public class IndexCatalog { - private final NitriteStore nitriteStore; - - public IndexCatalog(NitriteStore nitriteStore) { - this.nitriteStore = nitriteStore; - } - - public boolean hasIndexEntry(String collectionName, String field) { - NitriteMap indexMetaMap = getIndexMetaMap(collectionName); - if (!indexMetaMap.containsKey(field)) return false; - - IndexMeta indexMeta = indexMetaMap.get(field); - return indexMeta != null; - } - - public IndexEntry createIndexEntry(String collectionName, String field, String indexType) { - IndexEntry index = new IndexEntry(indexType, field, collectionName); - - IndexMeta indexMeta = new IndexMeta(); - indexMeta.setIndexEntry(index); - indexMeta.setIsDirty(new AtomicBoolean(false)); - indexMeta.setIndexMap(getIndexMapName(index)); - - getIndexMetaMap(collectionName).put(field, indexMeta); - - return index; - } - - public IndexEntry findIndexEntry(String collectionName, String field) { - IndexMeta meta = getIndexMetaMap(collectionName).get(field); - if (meta != null) { - return meta.getIndexEntry(); - } - return null; - } - - public boolean isDirtyIndex(String collectionName, String field) { - IndexMeta meta = getIndexMetaMap(collectionName).get(field); - return meta != null && meta.getIsDirty().get(); - } - - public Collection listIndexEntries(String collectionName) { - Set indexSet = new LinkedHashSet<>(); - for (IndexMeta indexMeta : getIndexMetaMap(collectionName).values()) { - indexSet.add(indexMeta.getIndexEntry()); - } - return Collections.unmodifiableSet(indexSet); - } - - public void dropIndexEntry(String collectionName, String field) { - IndexMeta meta = getIndexMetaMap(collectionName).get(field); - if (meta != null && meta.getIndexEntry() != null) { - String indexMapName = meta.getIndexMap(); - nitriteStore.openMap(indexMapName, Object.class, Object.class).drop(); - } - getIndexMetaMap(collectionName).remove(field); - } - - public void beginIndexing(String collectionName, String field) { - markDirty(collectionName, field, true); - } - - public void endIndexing(String collectionName, String field) { - markDirty(collectionName, field, false); - } - - private NitriteMap getIndexMetaMap(String collectionName) { - String indexMetaName = getIndexMetaName(collectionName); - return nitriteStore.openMap(indexMetaName, String.class, IndexMeta.class); - } - - private String getIndexMetaName(String collectionName) { - return INDEX_META_PREFIX + INTERNAL_NAME_SEPARATOR + collectionName; - } - - private String getIndexMapName(IndexEntry index) { - return INDEX_PREFIX + - INTERNAL_NAME_SEPARATOR + - index.getCollectionName() + - INTERNAL_NAME_SEPARATOR + - index.getField() + - INTERNAL_NAME_SEPARATOR + - index.getIndexType(); - } - - private void markDirty(String collectionName, String field, boolean dirty) { - IndexMeta meta = getIndexMetaMap(collectionName).get(field); - if (meta != null && meta.getIndexEntry() != null) { - meta.getIsDirty().set(dirty); - } - } -} diff --git a/nitrite/src/main/java/org/dizitart/no2/store/MapMetaData.java b/nitrite/src/main/java/org/dizitart/no2/store/MapMetaData.java new file mode 100644 index 000000000..840ebed23 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/store/MapMetaData.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.store; + +import lombok.Data; +import lombok.Getter; +import org.dizitart.no2.collection.Document; + +import java.util.HashSet; +import java.util.Set; + +import static org.dizitart.no2.common.Constants.TAG_MAP_METADATA; + +/** + * The Map metadata. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +@Data +public class MapMetaData implements MetaData { + @Getter + private Set mapNames; + + /** + * Instantiates a new {@link MapMetaData}. + * + * @param metadata the metadata + */ + public MapMetaData(Document metadata) { + populateInfo(metadata); + } + + @Override + public Document getInfo() { + return Document.createDocument(TAG_MAP_METADATA, mapNames); + } + + @SuppressWarnings("unchecked") + private void populateInfo(Document metadata) { + mapNames = (Set) metadata.get(TAG_MAP_METADATA, Set.class); + if (mapNames == null) { + mapNames = new HashSet<>(); + } + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/store/MetaData.java b/nitrite/src/main/java/org/dizitart/no2/store/MetaData.java new file mode 100644 index 000000000..24b4ac7b9 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/store/MetaData.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.store; + +import org.dizitart.no2.collection.Document; + +/** + * The Metadata interface. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +public interface MetaData { + /** + * Gets metadata of the instance. + * + * @return the info + */ + Document getInfo(); +} diff --git a/nitrite/src/main/java/org/dizitart/no2/store/NitriteMap.java b/nitrite/src/main/java/org/dizitart/no2/store/NitriteMap.java index 93956096f..5711fd77f 100644 --- a/nitrite/src/main/java/org/dizitart/no2/store/NitriteMap.java +++ b/nitrite/src/main/java/org/dizitart/no2/store/NitriteMap.java @@ -18,8 +18,8 @@ import org.dizitart.no2.collection.meta.Attributes; import org.dizitart.no2.collection.meta.MetadataAware; -import org.dizitart.no2.common.tuples.Pair; import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.tuples.Pair; import static org.dizitart.no2.common.Constants.META_MAP_NAME; import static org.dizitart.no2.common.util.StringUtils.isNullOrEmpty; @@ -44,31 +44,22 @@ public interface NitriteMap extends MetadataAware, AutoCloseable { boolean containsKey(Key key); /** - * Gets the value mapped with the specified key or `null` otherwise. + * Gets the value mapped with the specified key or null otherwise. * * @param key the key - * @return the value, or `null` if the key not found. + * @return the value, or null if the key not found. */ Value get(Key key); /** - * Gets the parent {@link NitriteStore} where this map is stored. - * - * @return the store where this map is stored. - */ - NitriteStore getStore(); - - /** - * Remove all entries in the map. + * Removes all entries in the map. */ void clear(); /** - * Gets name of this map. - * - * @return the name of this map. - */ - String getName(); + * Closes this {@link NitriteMap}. + * */ + void close(); /** * Gets a {@link RecordStream} view of the values contained in @@ -76,22 +67,22 @@ public interface NitriteMap extends MetadataAware, AutoCloseable { * * @return the collection view of all values in this map. */ - RecordStream values(); + Iterable values(); /** - * Removes the mapping for a key from this map if it is present. + * Gets a {@link RecordStream} view of the keys contained in this map. * - * @param key the key whose mapping is to be removed from this map. - * @return the value that has been removed. + * @return a set view of the keys contained in this map. */ - Value remove(Key key); + Iterable keys(); /** - * Gets a {@link RecordStream} view of the keys contained in this map. + * Removes the mapping for a key from this map if it is present. * - * @return a set view of the keys contained in this map. + * @param key the key whose mapping is to be removed from this map. + * @return the value that has been removed. */ - RecordStream keySet(); + Value remove(Key key); /** * Associates the specified value with the specified key in this map. @@ -120,13 +111,6 @@ public interface NitriteMap extends MetadataAware, AutoCloseable { */ Value putIfAbsent(Key key, Value value); - /** - * Gets a {@link RecordStream} view of the mappings contained in this map. - * - * @return a set view of the mappings contained in this map. - */ - RecordStream> entries(); - /** * Get the smallest key that is larger than the given key, or null if no * such key exists. @@ -168,13 +152,42 @@ public interface NitriteMap extends MetadataAware, AutoCloseable { */ boolean isEmpty(); + /** + * Gets the parent {@link NitriteStore} where this map is stored. + * + * @return the store where this map is stored. + */ + NitriteStore getStore(); + + /** + * Gets name of this map. + * + * @return the name of this map. + */ + String getName(); + + /** + * Gets a {@link RecordStream} view of the mappings contained in this map. + * + * @return a set view of the mappings contained in this map. + */ + RecordStream> entries(); + + /** + * Gets a reversed {@link RecordStream} view of the mappings contained in this map. + * + * @return the record stream + */ + RecordStream> reversedEntries(); + /** * Deletes the map from the store. */ void drop(); - void close(); - + /** + * Gets the attributes of this map. + * */ default Attributes getAttributes() { NitriteMap metaMap = getStore().openMap(META_MAP_NAME, String.class, Attributes.class); if (metaMap != null && !getName().contentEquals(META_MAP_NAME)) { @@ -183,6 +196,9 @@ default Attributes getAttributes() { return null; } + /** + * Sets the attributes for this map. + * */ default void setAttributes(Attributes attributes) { NitriteMap metaMap = getStore().openMap(META_MAP_NAME, String.class, Attributes.class); if (metaMap != null && !getName().contentEquals(META_MAP_NAME)) { @@ -190,6 +206,9 @@ default void setAttributes(Attributes attributes) { } } + /** + * Update last modified time of the map. + */ default void updateLastModifiedTime() { if (isNullOrEmpty(getName()) || META_MAP_NAME.equals(getName())) return; diff --git a/nitrite/src/main/java/org/dizitart/no2/store/NitriteRTree.java b/nitrite/src/main/java/org/dizitart/no2/store/NitriteRTree.java index a3f3a7173..6bca86a79 100644 --- a/nitrite/src/main/java/org/dizitart/no2/store/NitriteRTree.java +++ b/nitrite/src/main/java/org/dizitart/no2/store/NitriteRTree.java @@ -20,16 +20,65 @@ import org.dizitart.no2.common.RecordStream; /** + * Represents an R-Tree in the nitrite database. + * + * @param the type parameter + * @param the type parameter * @author Anindya Chatterjee. + * @since 4.0 */ -public interface NitriteRTree { +public interface NitriteRTree extends AutoCloseable { + /** + * Adds a key to the rtree. + * + * @param key the key + * @param nitriteId the nitrite id + */ void add(Key key, NitriteId nitriteId); + /** + * Removes a key from the rtree. + * + * @param key the key + * @param nitriteId the nitrite id + */ void remove(Key key, NitriteId nitriteId); + /** + * Finds the intersecting keys from the rtree. + * + * @param key the key + * @return the record stream + */ RecordStream findIntersectingKeys(Key key); + /** + * Finds the contained keys from the rtree. + * + * @param key the key + * @return the record stream + */ RecordStream findContainedKeys(Key key); + /** + * Gets the size of the rtree. + * + * @return the size + */ long size(); + + /** + * Closes this {@link NitriteRTree} instance. + * */ + void close(); + + /** + * Clears the data. + */ + void clear(); + + /** + * Drops this instance. + */ + void drop(); } diff --git a/nitrite/src/main/java/org/dizitart/no2/store/NitriteStore.java b/nitrite/src/main/java/org/dizitart/no2/store/NitriteStore.java index fbe528b3a..960b93b8f 100644 --- a/nitrite/src/main/java/org/dizitart/no2/store/NitriteStore.java +++ b/nitrite/src/main/java/org/dizitart/no2/store/NitriteStore.java @@ -18,7 +18,7 @@ import org.dizitart.no2.collection.NitriteCollection; import org.dizitart.no2.index.BoundingBox; -import org.dizitart.no2.module.NitritePlugin; +import org.dizitart.no2.common.module.NitritePlugin; import org.dizitart.no2.repository.ObjectRepository; import org.dizitart.no2.store.events.StoreEventListener; @@ -26,19 +26,23 @@ import java.util.Set; /** - * Represents a persistent storage for Nitrite database. + * Represents a storage for Nitrite database. * + * @param the type parameter * @author Anindya Chatterjee * @since 1.0 */ public interface NitriteStore extends NitritePlugin, AutoCloseable { + /** + * Opens or creates this nitrite store. + */ void openOrCreate(); /** * Checks whether this store is closed for further modification. * - * @return `true` if closed; `false` otherwise. + * @return true if closed; false otherwise. */ boolean isClosed(); @@ -66,14 +70,14 @@ public interface NitriteStore extends NitritePlugin, /** * Checks whether there are any unsaved changes. * - * @return `true` if there are any changes; `false` otherwise. + * @return true if here are any changes; false otherwise. */ boolean hasUnsavedChanges(); /** * Checks whether the store is opened in readonly mode. * - * @return `true` if the store is opened in readonly mode.; `false` otherwise. + * @return true if he store is opened in readonly mode; false otherwise. */ boolean isReadOnly(); @@ -84,22 +88,10 @@ public interface NitriteStore extends NitritePlugin, void commit(); /** - * Closes the file and the store. Unsaved changes are written to disk first. - */ - void close(); - - /** - * This method runs before {@link #close()}, to run cleanup routines. + * This method runs before store {@link #close()}, to run cleanup routines. */ void beforeClose(); - /** - * Gets the {@link IndexCatalog} instances from the store. - * - * @return the IndexCatalog instance. - */ - IndexCatalog getIndexCatalog(); - /** * Checks whether a map with the name already exists in the store or not. * @@ -110,8 +102,8 @@ public interface NitriteStore extends NitritePlugin, /** * Opens a {@link NitriteMap} with the default settings. The map is - * automatically create if it does not yet exist. If a map with this - * name is already open, this map is returned. + * automatically created if it does not yet exist. If a map with this + * name is already opened, this map is returned. * * @param the key type * @param the value type @@ -123,7 +115,14 @@ public interface NitriteStore extends NitritePlugin, NitriteMap openMap(String mapName, Class keyType, Class valueType); /** - * Removes a map from the store. + * Closes a {@link NitriteMap} in the store. + * + * @param mapName the map name + */ + void closeMap(String mapName); + + /** + * Removes a {@link NitriteMap} from the store. * * @param mapName the map name to remove. */ @@ -131,7 +130,7 @@ public interface NitriteStore extends NitritePlugin, /** * Opens a {@link NitriteRTree} with the default settings. The RTree is - * automatically create if it does not yet exist. If a RTree with this + * automatically created if it does not yet exist. If a RTree with this * name is already open, this RTree is returned. * * @param the key type @@ -143,6 +142,14 @@ public interface NitriteStore extends NitritePlugin, */ NitriteRTree openRTree(String rTreeName, Class keyType, Class valueType); + + /** + * Closes a RTree in the store. + * + * @param rTreeName the RTree name + */ + void closeRTree(String rTreeName); + /** * Removes a RTree from the store. * @@ -165,16 +172,24 @@ public interface NitriteStore extends NitritePlugin, void unsubscribe(StoreEventListener listener); /** - * Gets underlying store version. + * Gets the underlying store engine version. * * @return the store version */ String getStoreVersion(); /** - * Gets store config. + * Gets the store configuration. * * @return the store config */ Config getStoreConfig(); + + + /** + * Gets the store catalog. + * + * @return the catalog + */ + StoreCatalog getCatalog(); } diff --git a/nitrite/src/main/java/org/dizitart/no2/store/StoreCatalog.java b/nitrite/src/main/java/org/dizitart/no2/store/StoreCatalog.java new file mode 100644 index 000000000..9f7cb43dc --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/store/StoreCatalog.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.store; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.tuples.Pair; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static org.dizitart.no2.common.Constants.*; +import static org.dizitart.no2.common.util.ObjectUtils.getKeyName; +import static org.dizitart.no2.common.util.ObjectUtils.getKeyedRepositoryType; + +/** + * The nitrite store catalog containing the name of all collections, + * repositories and keyed-repositories. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +public class StoreCatalog { + private final NitriteMap catalogMap; + + /** + * Instantiates a new {@link StoreCatalog}. + * + * @param nitriteStore the nitrite store + */ + public StoreCatalog(NitriteStore nitriteStore) { + this.catalogMap = nitriteStore.openMap(COLLECTION_CATALOG, String.class, Document.class); + } + + /** + * Writes a new collection entry to the catalog. + * + * @param name the name + */ + public void writeCollectionEntry(String name) { + Document document = catalogMap.get(TAG_COLLECTIONS); + if (document == null) { + document = Document.createDocument(); + } + + // parse the document to create collection meta data object + MapMetaData metaData = new MapMetaData(document); + metaData.getMapNames().add(name); + + // convert the meta data object to document and save + catalogMap.put(TAG_COLLECTIONS, metaData.getInfo()); + } + + /** + * Writes a repository entry to the catalog. + * + * @param name the name + */ + public void writeRepositoryEntry(String name) { + Document document = catalogMap.get(TAG_REPOSITORIES); + if (document == null) { + document = Document.createDocument(); + } + + // parse the document to create collection meta data object + MapMetaData metaData = new MapMetaData(document); + metaData.getMapNames().add(name); + + // convert the meta data object to document and save + catalogMap.put(TAG_REPOSITORIES, metaData.getInfo()); + } + + /** + * Writes a keyed repository entries to the catalog + * + * @param name the name + */ + public void writeKeyedRepositoryEntries(String name) { + Document document = catalogMap.get(TAG_KEYED_REPOSITORIES); + if (document == null) { + document = Document.createDocument(); + } + + // parse the document to create collection meta data object + MapMetaData metaData = new MapMetaData(document); + metaData.getMapNames().add(name); + + catalogMap.put(TAG_KEYED_REPOSITORIES, metaData.getInfo()); + } + + /** + * Gets all collection names. + * + * @return the collection names + */ + public Set getCollectionNames() { + Document document = catalogMap.get(TAG_COLLECTIONS); + if (document == null) return new HashSet<>(); + + MapMetaData metaData = new MapMetaData(document); + return metaData.getMapNames(); + } + + /** + * Gets all repository names. + * + * @return the repository names + */ + public Set getRepositoryNames() { + Document document = catalogMap.get(TAG_REPOSITORIES); + if (document == null) return new HashSet<>(); + + MapMetaData metaData = new MapMetaData(document); + return metaData.getMapNames(); + } + + /** + * Gets all keyed repository names. + * + * @return the keyed repository names + */ + public Map> getKeyedRepositoryNames() { + Document document = catalogMap.get(TAG_KEYED_REPOSITORIES); + if (document == null) return new HashMap<>(); + + MapMetaData metaData = new MapMetaData(document); + Set keyedRepositoryNames = metaData.getMapNames(); + + Map> resultMap = new HashMap<>(); + for (String field : keyedRepositoryNames) { + String key = getKeyName(field); + String type = getKeyedRepositoryType(field); + + Set types; + if (resultMap.containsKey(key)) { + types = resultMap.get(key); + } else { + types = new HashSet<>(); + } + types.add(type); + resultMap.put(key, types); + } + return resultMap; + } + + /** + * Removes the entry from the catalog specified by name. + * + * @param name the name + */ + public void remove(String name) { + // iterate over all types of catalog and find which type contains the name + // remove the name from there + for (Pair entry : catalogMap.entries()) { + String catalogue = entry.getFirst(); + Document document = entry.getSecond(); + + MapMetaData metaData = new MapMetaData(document); + + if (metaData.getMapNames().contains(name)) { + metaData.getMapNames().remove(name); + catalogMap.put(catalogue, metaData.getInfo()); + break; + } + } + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/store/StoreConfig.java b/nitrite/src/main/java/org/dizitart/no2/store/StoreConfig.java index 2d3f8cd2f..9e3ea8106 100644 --- a/nitrite/src/main/java/org/dizitart/no2/store/StoreConfig.java +++ b/nitrite/src/main/java/org/dizitart/no2/store/StoreConfig.java @@ -23,7 +23,7 @@ * Represents a {@link NitriteStore} configuration. * * @author Anindya Chatterjee. - * @since 4.0.0 + * @since 4.0 */ public interface StoreConfig { /** @@ -36,7 +36,7 @@ public interface StoreConfig { /** * Indicates if the {@link NitriteStore} is a readonly store. * - * @return `true`, if readonly store; otherwise `false`. + * @return true, if readonly store; otherwise false. */ Boolean isReadOnly(); @@ -50,7 +50,7 @@ public interface StoreConfig { /** * Indicates if the {@link NitriteStore} is an in-memory store. * - * @return `true`, if in-memory store; otherwise `false`. + * @return true, if in-memory store; otherwise false. */ default boolean isInMemory() { return StringUtils.isNullOrEmpty(filePath()); diff --git a/nitrite/src/main/java/org/dizitart/no2/store/StoreMetaData.java b/nitrite/src/main/java/org/dizitart/no2/store/StoreMetaData.java new file mode 100644 index 000000000..13181bc73 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/store/StoreMetaData.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017-2020. Nitrite author or authors. + * + * Licensed 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.dizitart.no2.store; + +import lombok.Data; +import lombok.NoArgsConstructor; +import org.dizitart.no2.collection.Document; + +/** + * The nitrite database metadata. + * + * @author Anindya Chatterjee. + * @since 4.0 + */ +@Data +@NoArgsConstructor +public class StoreMetaData implements MetaData { + private Long createTime; + private String storeVersion; + private String nitriteVersion; + private Integer schemaVersion; + + /** + * Instantiates a new {@link StoreMetaData}. + * + * @param document the document + */ + public StoreMetaData(Document document) { + populateInfo(document); + } + + /** + * Gets the database info ina document. + * + * @return the info + */ + public Document getInfo() { + return Document.createDocument() + .put("createTime", createTime) + .put("storeVersion", storeVersion) + .put("nitriteVersion", nitriteVersion) + .put("schemaVersion", schemaVersion); + } + + private void populateInfo(Document document) { + createTime = document.get("createTime", Long.class); + storeVersion = document.get("storeVersion", String.class); + nitriteVersion = document.get("nitriteVersion", String.class); + schemaVersion = document.get("schemaVersion", Integer.class); + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/store/StoreModule.java b/nitrite/src/main/java/org/dizitart/no2/store/StoreModule.java index e04f56350..f49f27a63 100644 --- a/nitrite/src/main/java/org/dizitart/no2/store/StoreModule.java +++ b/nitrite/src/main/java/org/dizitart/no2/store/StoreModule.java @@ -1,10 +1,18 @@ package org.dizitart.no2.store; -import org.dizitart.no2.module.NitriteModule; +import org.dizitart.no2.common.module.NitriteModule; /** + * Represents a nitrite store module to load as a storage engine for the database. + * * @author Anindya Chatterjee + * @since 4.0 */ public interface StoreModule extends NitriteModule { + /** + * Gets the {@link NitriteStore} instance from this module. + * + * @return the store + */ NitriteStore getStore(); } diff --git a/nitrite/src/main/java/org/dizitart/no2/store/StoreSecurity.java b/nitrite/src/main/java/org/dizitart/no2/store/StoreSecurity.java deleted file mode 100644 index 1f0fa9453..000000000 --- a/nitrite/src/main/java/org/dizitart/no2/store/StoreSecurity.java +++ /dev/null @@ -1,144 +0,0 @@ -package org.dizitart.no2.store; - -import lombok.extern.slf4j.Slf4j; -import org.dizitart.no2.common.util.SecureString; -import org.dizitart.no2.exceptions.SecurityException; - -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.spec.InvalidKeySpecException; -import java.util.Arrays; -import java.util.Random; - -import static org.dizitart.no2.common.Constants.*; -import static org.dizitart.no2.common.util.StringUtils.isNullOrEmpty; - -/** - * @author Anindya Chatterjee - */ -@Slf4j -public class StoreSecurity { - private static final Random random = new SecureRandom(); - - private StoreSecurity() {} - - public static void authenticate(NitriteStore store, String username, String password, boolean existing) { - /* - * 1. Proper user password create - * 2. Proper user password open - * 3. Blank user password for secured store - * 4. Wrong user password for secured store - * 5. User Password for un-secured store - * */ - - if (!isNullOrEmpty(password) && !isNullOrEmpty(username)) { - /* - * 1. create new - * 2. open existing correct - * 3. open existing incorrect - * 4. open un-secured existing [how do I know if db already existing and user/pass not required?] - * */ - - if (!existing) { - byte[] salt = getNextSalt(); - byte[] hash = hash(password.toCharArray(), salt); - UserCredential userCredential = new UserCredential(); - userCredential.setPasswordHash(hash); - userCredential.setPasswordSalt(salt); - - NitriteMap userMap = store.openMap(USER_MAP, String.class, UserCredential.class); - userMap.put(username, userCredential); - } else { - NitriteMap userMap = store.openMap(USER_MAP, String.class, UserCredential.class); - UserCredential userCredential = userMap.get(username); - - if (userCredential != null) { - byte[] salt = userCredential.getPasswordSalt(); - byte[] expectedHash = userCredential.getPasswordHash(); - - if (notExpectedPassword(password.toCharArray(), salt, expectedHash)) { - throw new SecurityException("username or password is invalid"); - } - } else { - throw new SecurityException("username or password is invalid"); - } - } - } else if (existing) { - /* - * 1. create new un-secured - * 2. open un-secured - * */ - if (store.hasMap(USER_MAP)) { - throw new SecurityException("username or password is invalid"); - } - } - } - - public static void addOrUpdatePassword(NitriteStore store, boolean update, String username, - SecureString oldPassword, SecureString newPassword) { - NitriteMap userMap = null; - - if (update) { - userMap = store.openMap(USER_MAP, String.class, UserCredential.class); - UserCredential credential = userMap.get(username); - - if (credential != null) { - byte[] salt = credential.getPasswordSalt(); - byte[] expectedHash = credential.getPasswordHash(); - - if (notExpectedPassword(oldPassword.asString().toCharArray(), salt, expectedHash)) { - throw new SecurityException("username or password is invalid"); - } - } - } else { - if (store.hasMap(USER_MAP)) { - throw new SecurityException("cannot add new credentials"); - } - } - - if (userMap == null) { - userMap = store.openMap(USER_MAP, String.class, UserCredential.class); - } - - byte[] salt = getNextSalt(); - byte[] hash = hash(newPassword.asString().toCharArray(), salt); - - UserCredential userCredential = new UserCredential(); - userCredential.setPasswordHash(hash); - userCredential.setPasswordSalt(salt); - userMap.put(username, userCredential); - } - - private static boolean notExpectedPassword(char[] password, byte[] salt, byte[] expectedHash) { - byte[] pwdHash = hash(password, salt); - Arrays.fill(password, Character.MIN_VALUE); - if (pwdHash.length != expectedHash.length) return true; - for (int i = 0; i < pwdHash.length; i++) { - if (pwdHash[i] != expectedHash[i]) return true; - } - return false; - } - - private static byte[] getNextSalt() { - byte[] salt = new byte[16]; - random.nextBytes(salt); - return salt; - } - - private static byte[] hash(char[] password, byte[] salt) { - PBEKeySpec spec = new PBEKeySpec(password, salt, HASH_ITERATIONS, HASH_KEY_LENGTH); - Arrays.fill(password, Character.MIN_VALUE); - try { - SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); - return skf.generateSecret(spec).getEncoded(); - } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { - log.error("Error while hashing password", e); - throw new SecurityException("error while hashing a password: " - + e.getMessage()); - } finally { - spec.clearPassword(); - } - } -} diff --git a/nitrite/src/main/java/org/dizitart/no2/store/UserAuthenticationService.java b/nitrite/src/main/java/org/dizitart/no2/store/UserAuthenticationService.java new file mode 100644 index 000000000..9286d86c8 --- /dev/null +++ b/nitrite/src/main/java/org/dizitart/no2/store/UserAuthenticationService.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.store; + +import lombok.extern.slf4j.Slf4j; +import org.dizitart.no2.common.util.SecureString; +import org.dizitart.no2.exceptions.NitriteSecurityException; + +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.spec.InvalidKeySpecException; +import java.util.Arrays; + +import static org.dizitart.no2.common.Constants.*; +import static org.dizitart.no2.common.util.StringUtils.isNullOrEmpty; + +/** + * User authentication service for nitrite. + * + * @author Anindya Chatterjee + * @since 4.0 + */ +@Slf4j +public class UserAuthenticationService { + private final SecureRandom random; + private final NitriteStore store; + + /** + * Instantiates a new {@link UserAuthenticationService}. + * + * @param store the store + */ + public UserAuthenticationService(NitriteStore store) { + this.store = store; + this.random = new SecureRandom(); + } + + /** + * Authenticates a user if the authentication data already exists in the database. + * + * @param username the username + * @param password the password + * @param existing indicates if authentication data is already existing + */ + public void authenticate(String username, String password, boolean existing) { + if (!isNullOrEmpty(password) && !isNullOrEmpty(username)) { + if (!existing) { + byte[] salt = getNextSalt(); + byte[] hash = hash(password.toCharArray(), salt); + UserCredential userCredential = new UserCredential(); + userCredential.setPasswordHash(hash); + userCredential.setPasswordSalt(salt); + + NitriteMap userMap = store.openMap(USER_MAP, String.class, UserCredential.class); + userMap.put(username, userCredential); + } else { + NitriteMap userMap = store.openMap(USER_MAP, String.class, UserCredential.class); + UserCredential userCredential = userMap.get(username); + + if (userCredential != null) { + byte[] salt = userCredential.getPasswordSalt(); + byte[] expectedHash = userCredential.getPasswordHash(); + + if (notExpectedPassword(password.toCharArray(), salt, expectedHash)) { + throw new NitriteSecurityException("username or password is invalid"); + } + } else { + throw new NitriteSecurityException("username or password is invalid"); + } + } + } else if (existing) { + if (store.hasMap(USER_MAP)) { + throw new NitriteSecurityException("username or password is invalid"); + } + } + } + + /** + * Adds or updates the password for a user in the authentication data. + * + * @param update the update + * @param username the username + * @param oldPassword the old password + * @param newPassword the new password + */ + public void addOrUpdatePassword(boolean update, String username, + SecureString oldPassword, SecureString newPassword) { + NitriteMap userMap = null; + + if (update) { + userMap = store.openMap(USER_MAP, String.class, UserCredential.class); + UserCredential credential = userMap.get(username); + + if (credential != null) { + byte[] salt = credential.getPasswordSalt(); + byte[] expectedHash = credential.getPasswordHash(); + + if (notExpectedPassword(oldPassword.asString().toCharArray(), salt, expectedHash)) { + throw new NitriteSecurityException("username or password is invalid"); + } + } + } else { + if (store.hasMap(USER_MAP)) { + throw new NitriteSecurityException("cannot add new credentials"); + } + } + + if (userMap == null) { + userMap = store.openMap(USER_MAP, String.class, UserCredential.class); + } + + byte[] salt = getNextSalt(); + byte[] hash = hash(newPassword.asString().toCharArray(), salt); + + UserCredential userCredential = new UserCredential(); + userCredential.setPasswordHash(hash); + userCredential.setPasswordSalt(salt); + userMap.put(username, userCredential); + } + + + private byte[] getNextSalt() { + byte[] salt = new byte[16]; + random.nextBytes(salt); + return salt; + } + + private byte[] hash(char[] password, byte[] salt) { + PBEKeySpec spec = new PBEKeySpec(password, salt, HASH_ITERATIONS, HASH_KEY_LENGTH); + Arrays.fill(password, Character.MIN_VALUE); + try { + SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); + return skf.generateSecret(spec).getEncoded(); + } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { + log.error("Error while hashing password", e); + throw new NitriteSecurityException("error while hashing a password: " + + e.getMessage()); + } finally { + spec.clearPassword(); + } + } + + private boolean notExpectedPassword(char[] password, byte[] salt, byte[] expectedHash) { + byte[] pwdHash = hash(password, salt); + Arrays.fill(password, Character.MIN_VALUE); + if (pwdHash.length != expectedHash.length) return true; + for (int i = 0; i < pwdHash.length; i++) { + if (pwdHash[i] != expectedHash[i]) return true; + } + return false; + } +} diff --git a/nitrite/src/main/java/org/dizitart/no2/store/UserCredential.java b/nitrite/src/main/java/org/dizitart/no2/store/UserCredential.java index e849abe92..ff25a6333 100644 --- a/nitrite/src/main/java/org/dizitart/no2/store/UserCredential.java +++ b/nitrite/src/main/java/org/dizitart/no2/store/UserCredential.java @@ -24,8 +24,10 @@ import java.io.Serializable; /** - * @since 1.0 + * The user credential data for database authentication. + * * @author Anindya Chatterjee. + * @since 1.0 */ @Data public class UserCredential implements Serializable { diff --git a/nitrite/src/main/java/org/dizitart/no2/store/events/EventInfo.java b/nitrite/src/main/java/org/dizitart/no2/store/events/EventInfo.java index c2161ba2b..49bd27bc1 100644 --- a/nitrite/src/main/java/org/dizitart/no2/store/events/EventInfo.java +++ b/nitrite/src/main/java/org/dizitart/no2/store/events/EventInfo.java @@ -22,7 +22,10 @@ import org.dizitart.no2.NitriteConfig; /** + * The nitrite event details. + * * @author Anindya Chatterjee + * @since 4.0 */ @Data @NoArgsConstructor diff --git a/nitrite/src/main/java/org/dizitart/no2/store/events/StoreEventBus.java b/nitrite/src/main/java/org/dizitart/no2/store/events/StoreEventBus.java index 4e90ba489..a899b7701 100644 --- a/nitrite/src/main/java/org/dizitart/no2/store/events/StoreEventBus.java +++ b/nitrite/src/main/java/org/dizitart/no2/store/events/StoreEventBus.java @@ -19,8 +19,11 @@ import org.dizitart.no2.common.event.NitriteEventBus; /** - * @since 4.0.0 + * The event bus for nitrite store events. + * + * @see StoreEvents * @author Anindya Chatterjee. + * @since 4.0.0 */ public class StoreEventBus extends NitriteEventBus { @Override diff --git a/nitrite/src/main/java/org/dizitart/no2/store/events/StoreEventListener.java b/nitrite/src/main/java/org/dizitart/no2/store/events/StoreEventListener.java index 251d9b041..0e9a248ff 100644 --- a/nitrite/src/main/java/org/dizitart/no2/store/events/StoreEventListener.java +++ b/nitrite/src/main/java/org/dizitart/no2/store/events/StoreEventListener.java @@ -17,8 +17,17 @@ package org.dizitart.no2.store.events; /** + * Represents an event listener for store events. + * + * @see StoreEvents * @author Anindya Chatterjee + * @since 4.0 */ public interface StoreEventListener { + /** + * Executes when an event is fired. + * + * @param eventInfo the event info + */ void onEvent(EventInfo eventInfo); } diff --git a/nitrite/src/main/java/org/dizitart/no2/store/events/StoreEvents.java b/nitrite/src/main/java/org/dizitart/no2/store/events/StoreEvents.java index bd239b270..c5fbb36f5 100644 --- a/nitrite/src/main/java/org/dizitart/no2/store/events/StoreEvents.java +++ b/nitrite/src/main/java/org/dizitart/no2/store/events/StoreEvents.java @@ -17,11 +17,29 @@ package org.dizitart.no2.store.events; /** + * Nitrite store related events. + * * @author Anindya Chatterjee + * @since 4.0 */ public enum StoreEvents { + /** + * The store opened event. + */ Opened, + + /** + * The store commit event. + */ Commit, + + /** + * The store closing event. + */ Closing, + + /** + * The store closed event. + */ Closed } diff --git a/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryConfig.java b/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryConfig.java index 76b559a17..377075e02 100644 --- a/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryConfig.java +++ b/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryConfig.java @@ -11,7 +11,10 @@ import java.util.Set; /** + * The in-memory nitrite store config. + * * @author Anindya Chatterjee + * @since 4.0 */ @Accessors(fluent = true) public class InMemoryConfig implements StoreConfig { @@ -19,6 +22,9 @@ public class InMemoryConfig implements StoreConfig { @Setter(AccessLevel.PACKAGE) private Set eventListeners; + /** + * Instantiates a new {@link InMemoryConfig}. + */ InMemoryConfig() { this.eventListeners = new HashSet<>(); } diff --git a/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryMap.java b/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryMap.java index ac1f5ce5f..9fa4d0096 100644 --- a/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryMap.java +++ b/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryMap.java @@ -1,6 +1,5 @@ package org.dizitart.no2.store.memory; -import org.dizitart.no2.common.NullEntry; import org.dizitart.no2.common.RecordStream; import org.dizitart.no2.common.tuples.Pair; import org.dizitart.no2.common.util.Comparables; @@ -15,18 +14,27 @@ import static org.dizitart.no2.common.util.ValidationUtils.notNull; /** + * The in-memory {@link NitriteMap}. + * + * @param the type parameter + * @param the type parameter * @author Anindya Chatterjee + * @since 4.0 */ public class InMemoryMap implements NitriteMap { private final NavigableMap backingMap; - private final NavigableMap nullEntryMap; private final NitriteStore nitriteStore; private final String mapName; + /** + * Instantiates a new {@link InMemoryMap}. + * + * @param mapName the map name + * @param nitriteStore the nitrite store + */ public InMemoryMap(String mapName, NitriteStore nitriteStore) { this.mapName = mapName; this.nitriteStore = nitriteStore; - this.nullEntryMap = new ConcurrentSkipListMap<>(); this.backingMap = new ConcurrentSkipListMap<>((o1, o2) -> Comparables.compare((Comparable) o1, (Comparable) o2)); @@ -34,17 +42,11 @@ public InMemoryMap(String mapName, NitriteStore nitriteStore) { @Override public boolean containsKey(Key key) { - if (key == null) { - return nullEntryMap.containsKey(NullEntry.getInstance()); - } return backingMap.containsKey(key); } @Override public Value get(Key key) { - if (key == null) { - return nullEntryMap.get(NullEntry.getInstance()); - } return backingMap.get(key); } @@ -56,7 +58,6 @@ public NitriteStore getStore() { @Override public void clear() { backingMap.clear(); - nullEntryMap.clear(); updateLastModifiedTime(); } @@ -67,67 +68,31 @@ public String getName() { @Override public RecordStream values() { - return RecordStream.fromCombined(backingMap.values(), nullEntryMap.values()); + return RecordStream.fromIterable(backingMap.values()); } @Override public Value remove(Key key) { - Value value; - if (key == null) { - value = nullEntryMap.remove(NullEntry.getInstance()); - } else { - value = backingMap.remove(key); - } + Value value = backingMap.remove(key); updateLastModifiedTime(); return value; } @Override - public RecordStream keySet() { - return RecordStream.fromIterable(() -> new Iterator() { - final Iterator keyIterator = backingMap.keySet().iterator(); - final Iterator nullEntryIterator = nullEntryMap.keySet().iterator(); - - @Override - public boolean hasNext() { - boolean result = nullEntryIterator.hasNext(); - if (!result) { - return keyIterator.hasNext(); - } - return true; - } - - @Override - public Key next() { - if (nullEntryIterator.hasNext()) { - return null; - } else { - return keyIterator.next(); - } - } - }); + public RecordStream keys() { + return RecordStream.fromIterable(backingMap.keySet()); } @Override public void put(Key key, Value value) { notNull(value, "value cannot be null"); - if (key == null) { - nullEntryMap.put(NullEntry.getInstance(), value); - } else { - Map.Entry firstEntry = backingMap.firstEntry(); - if (firstEntry != null) { - if (!firstEntry.getKey().getClass().equals(key.getClass())) { - return; - } - } - backingMap.put(key, value); - } + backingMap.put(key, value); updateLastModifiedTime(); } @Override public long size() { - return backingMap.size() + nullEntryMap.size(); + return backingMap.size(); } @Override @@ -144,30 +109,12 @@ public Value putIfAbsent(Key key, Value value) { @Override public RecordStream> entries() { - return RecordStream.fromIterable(() -> new Iterator>() { - private final Iterator> entryIterator = backingMap.entrySet().iterator(); - private final Iterator> nullEntryIterator = nullEntryMap.entrySet().iterator(); - - @Override - public boolean hasNext() { - boolean result = nullEntryIterator.hasNext(); - if (!result) { - return entryIterator.hasNext(); - } - return true; - } + return getStream(backingMap); + } - @Override - public Pair next() { - if (nullEntryIterator.hasNext()) { - Map.Entry entry = nullEntryIterator.next(); - return new Pair<>(null, entry.getValue()); - } else { - Map.Entry entry = entryIterator.next(); - return new Pair<>(entry.getKey(), entry.getValue()); - } - } - }); + @Override + public RecordStream> reversedEntries() { + return getStream(backingMap.descendingMap()); } @Override @@ -204,7 +151,7 @@ public Key floorKey(Key key) { @Override public boolean isEmpty() { - return backingMap.isEmpty() && nullEntryMap.isEmpty(); + return backingMap.isEmpty(); } @Override @@ -215,6 +162,23 @@ public void drop() { @Override public void close() { + // nothing to close + } + private RecordStream> getStream(NavigableMap primaryMap) { + return RecordStream.fromIterable(() -> new Iterator>() { + private final Iterator> entryIterator = + primaryMap.entrySet().iterator(); + @Override + public boolean hasNext() { + return entryIterator.hasNext(); + } + + @Override + public Pair next() { + Map.Entry entry = entryIterator.next(); + return new Pair<>(entry.getKey(), entry.getValue()); + } + }); } } diff --git a/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryModuleBuilder.java b/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryModuleBuilder.java index 94e352ff8..c9bfa6fb8 100644 --- a/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryModuleBuilder.java +++ b/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryModuleBuilder.java @@ -8,7 +8,10 @@ import java.util.Set; /** + * The in-memory store module builder. + * * @author Anindya Chatterjee + * @since 4.0 */ @Getter @Accessors(fluent = true) @@ -16,16 +19,30 @@ public class InMemoryModuleBuilder { private final Set eventListeners; private final InMemoryConfig dbConfig; + /** + * Instantiates a new {@link InMemoryModuleBuilder}. + */ InMemoryModuleBuilder() { dbConfig = new InMemoryConfig(); eventListeners = new HashSet<>(); } + /** + * Adds a {@link StoreEventListener} to the in-memory module builder. + * + * @param listener the listener + * @return the in memory module builder + */ public InMemoryModuleBuilder addStoreEventListener(StoreEventListener listener) { eventListeners.add(listener); return this; } + /** + * Builds an in-memory store module. + * + * @return the in memory store module + */ public InMemoryStoreModule build() { InMemoryStoreModule module = new InMemoryStoreModule(); dbConfig.eventListeners(eventListeners()); diff --git a/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryRTree.java b/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryRTree.java index 3a418abad..293951224 100644 --- a/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryRTree.java +++ b/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryRTree.java @@ -12,12 +12,19 @@ import java.util.concurrent.ConcurrentHashMap; /** + * The in-memory {@link NitriteRTree}. * + * @param the type parameter + * @param the type parameter * @author Anindya Chatterjee + * @since 4.0 */ public class InMemoryRTree implements NitriteRTree { private final Map backingMap; + /** + * Instantiates a new {@link InMemoryRTree}. + */ public InMemoryRTree() { this.backingMap = new ConcurrentHashMap<>(); } @@ -100,36 +107,94 @@ private SpatialKey getKey(Key key, long id) { key.getMaxX(), key.getMinY(), key.getMaxY()); } + @Override + public void close() { + + } + + @Override + public void clear() { + backingMap.clear(); + } + + @Override + public void drop() { + backingMap.clear(); + } + + /** + * The type Spatial key. + */ static class SpatialKey { private final long id; private final float[] minMax; + /** + * Instantiates a new Spatial key. + * + * @param id the id + * @param minMax the min max + */ public SpatialKey(long id, float... minMax) { this.id = id; this.minMax = minMax; } + /** + * Min float. + * + * @param dim the dim + * @return the float + */ public float min(int dim) { return minMax[dim + dim]; } + /** + * Sets min. + * + * @param dim the dim + * @param x the x + */ public void setMin(int dim, float x) { minMax[dim + dim] = x; } + /** + * Max float. + * + * @param dim the dim + * @return the float + */ public float max(int dim) { return minMax[dim + dim + 1]; } + /** + * Sets max. + * + * @param dim the dim + * @param x the x + */ public void setMax(int dim, float x) { minMax[dim + dim + 1] = x; } + /** + * Gets id. + * + * @return the id + */ public long getId() { return id; } + /** + * Is null boolean. + * + * @return the boolean + */ public boolean isNull() { return minMax.length == 0; } @@ -153,6 +218,12 @@ public boolean equals(Object other) { return equalsIgnoringId(o); } + /** + * Equals ignoring id boolean. + * + * @param o the o + * @return the boolean + */ public boolean equalsIgnoringId(SpatialKey o) { return Arrays.equals(minMax, o.minMax); } diff --git a/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryStore.java b/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryStore.java index a24bd993f..e801a0e14 100644 --- a/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryStore.java +++ b/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryStore.java @@ -13,13 +13,19 @@ import static org.dizitart.no2.common.Constants.NITRITE_VERSION; /** + * The nitrite in-memory store. + * * @author Anindya Chatterjee + * @since 4.0 */ public final class InMemoryStore extends AbstractNitriteStore { private final Map> nitriteMapRegistry; private final Map> nitriteRTreeMapRegistry; private volatile boolean closed = false; + /** + * Instantiates a new {@link InMemoryStore}. + */ public InMemoryStore() { super(); this.nitriteMapRegistry = new ConcurrentHashMap<>(); @@ -53,8 +59,19 @@ public void commit() { } @Override - public void close() { + public void close() throws Exception { closed = true; + + for (NitriteMap map : nitriteMapRegistry.values()) { + map.close(); + } + + for (NitriteRTree rTree : nitriteRTreeMapRegistry.values()) { + rTree.close(); + } + + nitriteMapRegistry.clear(); + nitriteRTreeMapRegistry.clear(); alert(StoreEvents.Closed); } @@ -76,6 +93,18 @@ public NitriteMap openMap(String mapName, Class keyT return nitriteMap; } + @Override + public void closeMap(String mapName) { + // nothing to close as it is volatile map, moreover, + // removing it form registry means loosing the map + } + + @Override + public void closeRTree(String rTreeName) { + // nothing to close as it is volatile map, moreover, + // removing it form registry means loosing the map + } + @Override public void removeMap(String mapName) { if (nitriteMapRegistry.containsKey(mapName)) { diff --git a/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryStoreModule.java b/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryStoreModule.java index 21af18b6f..e32ac6c96 100644 --- a/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryStoreModule.java +++ b/nitrite/src/main/java/org/dizitart/no2/store/memory/InMemoryStoreModule.java @@ -2,24 +2,37 @@ import lombok.AccessLevel; import lombok.Setter; -import org.dizitart.no2.module.NitritePlugin; +import org.dizitart.no2.common.module.NitritePlugin; import org.dizitart.no2.store.NitriteStore; import org.dizitart.no2.store.StoreModule; import java.util.Set; +import static org.dizitart.no2.common.util.Iterables.setOf; + /** + * The in-memory store module for nitrite. + * * @author Anindya Chatterjee + * @since 4.0 */ public class InMemoryStoreModule implements StoreModule { @Setter(AccessLevel.PACKAGE) private InMemoryConfig storeConfig; + /** + * Instantiates a new {@link InMemoryStoreModule}. + */ public InMemoryStoreModule() { this.storeConfig = new InMemoryConfig(); } + /** + * Creates an {@link InMemoryModuleBuilder} to configure the in-memory store. + * + * @return the in memory module builder + */ public static InMemoryModuleBuilder withConfig() { return new InMemoryModuleBuilder(); } diff --git a/nitrite/src/main/java/org/dizitart/no2/transaction/ChangeType.java b/nitrite/src/main/java/org/dizitart/no2/transaction/ChangeType.java index 2768c6894..6c4ab7323 100644 --- a/nitrite/src/main/java/org/dizitart/no2/transaction/ChangeType.java +++ b/nitrite/src/main/java/org/dizitart/no2/transaction/ChangeType.java @@ -1,17 +1,69 @@ package org.dizitart.no2.transaction; /** + * Represents a change type in a transaction. + * * @author Anindya Chatterjee + * @since 4.0 */ enum ChangeType { + /** + * Insert + */ Insert, + + /** + * Update. + */ Update, + + /** + * Remove. + */ Remove, + + /** + * Clear. + */ Clear, + + /** + * Create index. + */ CreateIndex, + + /** + * Rebuild index. + */ RebuildIndex, + + /** + * Drop index. + */ DropIndex, + + /** + * Drop all indices. + */ DropAllIndices, + + /** + * Drop collection. + */ DropCollection, - SetAttribute + + /** + * Set attribute. + */ + SetAttribute, + + /** + * Add processor + * */ + AddProcessor, + + /** + * Remove processor + * */ + RemoveProcessor, } diff --git a/nitrite/src/main/java/org/dizitart/no2/transaction/Command.java b/nitrite/src/main/java/org/dizitart/no2/transaction/Command.java index 4335e49de..c7856c234 100644 --- a/nitrite/src/main/java/org/dizitart/no2/transaction/Command.java +++ b/nitrite/src/main/java/org/dizitart/no2/transaction/Command.java @@ -1,8 +1,14 @@ package org.dizitart.no2.transaction; /** + * Represents an operation in a transaction. + * * @author Anindya Chatterjee + * @since 4.0 */ interface Command { + /** + * Executes the command during transaction commit or rollback. + */ void execute(); } diff --git a/nitrite/src/main/java/org/dizitart/no2/transaction/DefaultTransactionalCollection.java b/nitrite/src/main/java/org/dizitart/no2/transaction/DefaultTransactionalCollection.java index a9dc85a26..d64e7ec91 100644 --- a/nitrite/src/main/java/org/dizitart/no2/transaction/DefaultTransactionalCollection.java +++ b/nitrite/src/main/java/org/dizitart/no2/transaction/DefaultTransactionalCollection.java @@ -1,5 +1,6 @@ package org.dizitart.no2.transaction; +import lombok.Data; import org.dizitart.no2.Nitrite; import org.dizitart.no2.NitriteConfig; import org.dizitart.no2.collection.*; @@ -7,18 +8,21 @@ import org.dizitart.no2.collection.events.CollectionEventListener; import org.dizitart.no2.collection.meta.Attributes; import org.dizitart.no2.collection.operation.CollectionOperations; +import org.dizitart.no2.common.Fields; import org.dizitart.no2.common.WriteResult; import org.dizitart.no2.common.event.EventBus; import org.dizitart.no2.common.event.NitriteEventBus; import org.dizitart.no2.exceptions.*; import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexEntry; +import org.dizitart.no2.index.IndexDescriptor; import org.dizitart.no2.index.IndexOptions; import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.processors.Processor; import org.dizitart.no2.store.NitriteMap; import org.dizitart.no2.store.NitriteStore; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.concurrent.atomic.AtomicReference; @@ -33,7 +37,9 @@ /** * @author Anindya Chatterjee + * @since 4.0 */ +@Data class DefaultTransactionalCollection implements NitriteCollection { private final NitriteCollection primary; private final TransactionContext transactionContext; @@ -226,23 +232,12 @@ public WriteResult remove(Filter filter, boolean justOne) { } @Override - public DocumentCursor find() { - checkOpened(); - try { - readLock.lock(); - return collectionOperations.find(); - } finally { - readLock.unlock(); - } - } - - @Override - public DocumentCursor find(Filter filter) { + public DocumentCursor find(Filter filter, FindOptions findOptions) { checkOpened(); try { readLock.lock(); - return collectionOperations.find(filter); + return collectionOperations.find(filter, findOptions); } finally { readLock.unlock(); } @@ -267,18 +262,44 @@ public String getName() { } @Override - public void createIndex(String field, IndexOptions indexOptions) { + public void addProcessor(Processor processor) { checkOpened(); - notNull(field, "field cannot be null"); + notNull(processor, "a null processor cannot be added"); + collectionOperations.addProcessor(processor); + + JournalEntry journalEntry = new JournalEntry(); + journalEntry.setChangeType(ChangeType.AddProcessor); + journalEntry.setCommit(() -> primary.addProcessor(processor)); + journalEntry.setRollback(() -> primary.removeProcessor(processor)); + transactionContext.getJournal().add(journalEntry); + } + + @Override + public void removeProcessor(Processor processor) { + checkOpened(); + notNull(processor, "a null processor cannot be removed"); + collectionOperations.addProcessor(processor); + + JournalEntry journalEntry = new JournalEntry(); + journalEntry.setChangeType(ChangeType.RemoveProcessor); + journalEntry.setCommit(() -> primary.removeProcessor(processor)); + journalEntry.setRollback(() -> primary.addProcessor(processor)); + transactionContext.getJournal().add(journalEntry); + } + + @Override + public void createIndex(IndexOptions indexOptions, String... fieldNames) { + checkOpened(); + notNull(fieldNames, "fieldNames cannot be null"); // by default async is false while creating index try { + Fields fields = Fields.withNames(fieldNames); writeLock.lock(); if (indexOptions == null) { - collectionOperations.createIndex(field, IndexType.Unique, false); + collectionOperations.createIndex(fields, IndexType.UNIQUE); } else { - collectionOperations.createIndex(field, indexOptions.getIndexType(), - indexOptions.isAsync()); + collectionOperations.createIndex(fields, indexOptions.getIndexType()); } } finally { writeLock.unlock(); @@ -286,46 +307,47 @@ public void createIndex(String field, IndexOptions indexOptions) { JournalEntry journalEntry = new JournalEntry(); journalEntry.setChangeType(ChangeType.CreateIndex); - journalEntry.setCommit(() -> primary.createIndex(field, indexOptions)); - journalEntry.setRollback(() -> primary.dropIndex(field)); + journalEntry.setCommit(() -> primary.createIndex(indexOptions, fieldNames)); + journalEntry.setRollback(() -> primary.dropIndex(fieldNames)); transactionContext.getJournal().add(journalEntry); } @Override - public void rebuildIndex(String field, boolean isAsync) { + public void rebuildIndex(String... fieldNames) { checkOpened(); - notNull(field, "field cannot be null"); + notNull(fieldNames, "fieldNames cannot be null"); - IndexEntry indexEntry; + IndexDescriptor indexDescriptor; try { + Fields fields = Fields.withNames(fieldNames); readLock.lock(); - indexEntry = collectionOperations.findIndex(field); + indexDescriptor = collectionOperations.findIndex(fields); } finally { readLock.unlock(); } - if (indexEntry != null) { - validateRebuildIndex(indexEntry); + if (indexDescriptor != null) { + validateRebuildIndex(indexDescriptor); try { writeLock.lock(); - collectionOperations.rebuildIndex(indexEntry, isAsync); + collectionOperations.rebuildIndex(indexDescriptor); } finally { writeLock.unlock(); } } else { - throw new IndexingException(field + " is not indexed"); + throw new IndexingException(Arrays.toString(fieldNames) + " is not indexed"); } JournalEntry journalEntry = new JournalEntry(); journalEntry.setChangeType(ChangeType.RebuildIndex); - journalEntry.setCommit(() -> primary.rebuildIndex(field, isAsync)); - journalEntry.setRollback(() -> primary.rebuildIndex(field, isAsync)); + journalEntry.setCommit(() -> primary.rebuildIndex(fieldNames)); + journalEntry.setRollback(() -> primary.rebuildIndex(fieldNames)); transactionContext.getJournal().add(journalEntry); } @Override - public Collection listIndices() { + public Collection listIndices() { checkOpened(); try { @@ -337,60 +359,62 @@ public Collection listIndices() { } @Override - public boolean hasIndex(String field) { + public boolean hasIndex(String... fieldNames) { checkOpened(); - notNull(field, "field cannot be null"); + notNull(fieldNames, "fieldNames cannot be null"); try { + Fields fields = Fields.withNames(fieldNames); readLock.lock(); - return collectionOperations.hasIndex(field); + return collectionOperations.hasIndex(fields); } finally { readLock.unlock(); } } @Override - public boolean isIndexing(String field) { + public boolean isIndexing(String... fieldNames) { checkOpened(); - notNull(field, "field cannot be null"); + notNull(fieldNames, "fieldNames cannot be null"); try { + Fields fields = Fields.withNames(fieldNames); readLock.lock(); - return collectionOperations.isIndexing(field); + return collectionOperations.isIndexing(fields); } finally { readLock.unlock(); } } @Override - public void dropIndex(String field) { + public void dropIndex(String... fieldNames) { checkOpened(); - notNull(field, "field cannot be null"); + notNull(fieldNames, "fieldNames cannot be null"); + Fields fields = Fields.withNames(fieldNames); try { writeLock.lock(); - collectionOperations.dropIndex(field); + collectionOperations.dropIndex(fields); } finally { writeLock.unlock(); } - final AtomicReference indexEntry = new AtomicReference<>(); + final AtomicReference indexEntry = new AtomicReference<>(); JournalEntry journalEntry = new JournalEntry(); journalEntry.setChangeType(ChangeType.DropIndex); journalEntry.setCommit(() -> { - for (IndexEntry entry : primary.listIndices()) { - if (entry.getField().equals(field)) { + for (IndexDescriptor entry : primary.listIndices()) { + if (entry.getIndexFields().equals(fields)) { indexEntry.set(entry); break; } } - primary.dropIndex(field); + primary.dropIndex(fieldNames); }); journalEntry.setRollback(() -> { if (indexEntry.get() != null) { - primary.createIndex(indexEntry.get().getField(), - indexOptions(indexEntry.get().getIndexType())); + primary.createIndex(indexOptions(indexEntry.get().getIndexType()), fieldNames); } }); transactionContext.getJournal().add(journalEntry); @@ -407,7 +431,7 @@ public void dropAllIndices() { writeLock.unlock(); } - List indexEntries = new ArrayList<>(); + List indexEntries = new ArrayList<>(); JournalEntry journalEntry = new JournalEntry(); journalEntry.setChangeType(ChangeType.DropAllIndices); @@ -416,8 +440,9 @@ public void dropAllIndices() { primary.dropAllIndices(); }); journalEntry.setRollback(() -> { - for (IndexEntry indexEntry : indexEntries) { - primary.createIndex(indexEntry.getField(), indexOptions(indexEntry.getIndexType())); + for (IndexDescriptor indexDescriptor : indexEntries) { + String[] fieldNames = indexDescriptor.getIndexFields().getFieldNames().toArray(new String[0]); + primary.createIndex(indexOptions(indexDescriptor.getIndexType()), fieldNames); } }); transactionContext.getJournal().add(journalEntry); @@ -462,7 +487,7 @@ public void drop() { isDropped = true; List documentList = new ArrayList<>(); - List indexEntries = new ArrayList<>(); + List indexEntries = new ArrayList<>(); JournalEntry journalEntry = new JournalEntry(); journalEntry.setChangeType(ChangeType.DropCollection); @@ -474,8 +499,9 @@ public void drop() { journalEntry.setRollback(() -> { NitriteCollection collection = nitrite.getCollection(collectionName); - for (IndexEntry indexEntry : indexEntries) { - collection.createIndex(indexEntry.getField(), indexOptions(indexEntry.getIndexType())); + for (IndexDescriptor indexDescriptor : indexEntries) { + String[] fieldNames = indexDescriptor.getIndexFields().getFieldNames().toArray(new String[0]); + collection.createIndex(indexOptions(indexDescriptor.getIndexType()), fieldNames); } for (Document document : documentList) { @@ -493,7 +519,11 @@ public boolean isDropped() { @Override public boolean isOpen() { if (nitriteStore == null || nitriteStore.isClosed() || isDropped) { - close(); + try { + close(); + } catch (Exception e) { + throw new NitriteIOException("failed to close the database", e); + } return false; } else return true; } @@ -624,11 +654,12 @@ private void closeEventBus() { eventBus = null; } - private void validateRebuildIndex(IndexEntry indexEntry) { - notNull(indexEntry, "index cannot be null"); + private void validateRebuildIndex(IndexDescriptor indexDescriptor) { + notNull(indexDescriptor, "indexEntry cannot be null"); - if (isIndexing(indexEntry.getField())) { - throw new IndexingException("indexing on value " + indexEntry.getField() + " is currently running"); + String[] fieldNames = indexDescriptor.getIndexFields().getFieldNames().toArray(new String[0]); + if (isIndexing(fieldNames)) { + throw new IndexingException("indexing on value " + indexDescriptor.getIndexFields() + " is currently running"); } } } diff --git a/nitrite/src/main/java/org/dizitart/no2/transaction/DefaultTransactionalRepository.java b/nitrite/src/main/java/org/dizitart/no2/transaction/DefaultTransactionalRepository.java index b7513d63d..54bb8c62a 100644 --- a/nitrite/src/main/java/org/dizitart/no2/transaction/DefaultTransactionalRepository.java +++ b/nitrite/src/main/java/org/dizitart/no2/transaction/DefaultTransactionalRepository.java @@ -2,14 +2,16 @@ import org.dizitart.no2.NitriteConfig; import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.FindOptions; import org.dizitart.no2.collection.NitriteCollection; import org.dizitart.no2.collection.events.CollectionEventListener; import org.dizitart.no2.collection.meta.Attributes; import org.dizitart.no2.common.WriteResult; import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexEntry; +import org.dizitart.no2.index.IndexDescriptor; import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.mapper.NitriteMapper; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.common.processors.Processor; import org.dizitart.no2.repository.Cursor; import org.dizitart.no2.repository.ObjectRepository; import org.dizitart.no2.repository.RepositoryOperations; @@ -23,6 +25,7 @@ /** * @author Anindya Chatterjee + * @since 4.0 */ class DefaultTransactionalRepository implements ObjectRepository { private final Class type; @@ -43,33 +46,43 @@ public DefaultTransactionalRepository(Class type, } @Override - public void createIndex(String field, IndexOptions indexOptions) { - backingCollection.createIndex(field, indexOptions); + public void addProcessor(Processor processor) { + backingCollection.addProcessor(processor); } @Override - public void rebuildIndex(String field, boolean isAsync) { - backingCollection.rebuildIndex(field, isAsync); + public void removeProcessor(Processor processor) { + backingCollection.removeProcessor(processor); } @Override - public Collection listIndices() { + public void createIndex(IndexOptions indexOptions, String... fieldNames) { + backingCollection.createIndex(indexOptions, fieldNames); + } + + @Override + public void rebuildIndex(String... fieldNames) { + backingCollection.rebuildIndex(fieldNames); + } + + @Override + public Collection listIndices() { return backingCollection.listIndices(); } @Override - public boolean hasIndex(String field) { - return backingCollection.hasIndex(field); + public boolean hasIndex(String... fieldNames) { + return backingCollection.hasIndex(fieldNames); } @Override - public boolean isIndexing(String field) { - return backingCollection.isIndexing(field); + public boolean isIndexing(String... fieldNames) { + return backingCollection.isIndexing(fieldNames); } @Override - public void dropIndex(String field) { - backingCollection.dropIndex(field); + public void dropIndex(String... fieldNames) { + backingCollection.dropIndex(fieldNames); } @Override @@ -88,6 +101,7 @@ public WriteResult insert(T[] elements) { @Override public WriteResult update(T element, boolean insertIfAbsent) { notNull(element, "a null object cannot be used for update"); + return update(operations.createUniqueFilter(element), element, insertIfAbsent); } @@ -129,13 +143,8 @@ public void clear() { } @Override - public Cursor find() { - return operations.find(type); - } - - @Override - public Cursor find(Filter filter) { - return operations.find(filter, type); + public Cursor find(Filter filter, FindOptions findOptions) { + return operations.find(filter, findOptions, type); } @Override @@ -211,6 +220,6 @@ public NitriteCollection getDocumentCollection() { private void initialize() { NitriteMapper nitriteMapper = nitriteConfig.nitriteMapper(); this.operations = new RepositoryOperations(type, nitriteMapper, backingCollection); - this.operations.createIndexes(); + this.operations.createIndices(); } } diff --git a/nitrite/src/main/java/org/dizitart/no2/transaction/JournalEntry.java b/nitrite/src/main/java/org/dizitart/no2/transaction/JournalEntry.java index 492edf39c..73de9719a 100644 --- a/nitrite/src/main/java/org/dizitart/no2/transaction/JournalEntry.java +++ b/nitrite/src/main/java/org/dizitart/no2/transaction/JournalEntry.java @@ -5,7 +5,10 @@ import lombok.NoArgsConstructor; /** + * Represents a transaction journal entry. + * * @author Anindya Chatterjee + * @since 4.0 */ @Data @AllArgsConstructor diff --git a/nitrite/src/main/java/org/dizitart/no2/transaction/NitriteTransaction.java b/nitrite/src/main/java/org/dizitart/no2/transaction/NitriteTransaction.java index 6f6b3549f..63fa00a0b 100644 --- a/nitrite/src/main/java/org/dizitart/no2/transaction/NitriteTransaction.java +++ b/nitrite/src/main/java/org/dizitart/no2/transaction/NitriteTransaction.java @@ -8,6 +8,7 @@ import org.dizitart.no2.collection.NitriteCollection; import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.common.concurrent.LockService; +import org.dizitart.no2.common.module.NitriteModule; import org.dizitart.no2.exceptions.TransactionException; import org.dizitart.no2.repository.ObjectRepository; import org.dizitart.no2.store.NitriteMap; @@ -20,6 +21,7 @@ /** * @author Anindya Chatterjee + * @since 4.0 */ @Slf4j class NitriteTransaction implements Transaction { @@ -228,16 +230,20 @@ public void rollback() { @Override public void close() { - state = State.Closed; - for (TransactionContext context : contextMap.values()) { - context.getActive().set(false); - } + try { + state = State.Closed; + for (TransactionContext context : contextMap.values()) { + context.getActive().set(false); + } - this.contextMap.clear(); - this.collectionRegistry.clear(); - this.repositoryRegistry.clear(); - this.undoRegistry.clear(); - this.transactionalStore.close(); + this.contextMap.clear(); + this.collectionRegistry.clear(); + this.repositoryRegistry.clear(); + this.undoRegistry.clear(); + this.transactionalStore.close(); + } catch (Exception e) { + throw new TransactionException("transaction failed to close", e); + } } private void prepare() { @@ -250,8 +256,12 @@ private void prepare() { NitriteStore nitriteStore = nitrite.getStore(); NitriteConfig nitriteConfig = nitrite.getConfig(); - this.transactionalStore = new TransactionalStore<>(nitriteStore); - this.transactionalConfig = new TransactionalConfig(nitriteConfig, transactionalStore); + this.transactionalConfig = new TransactionalConfig(nitriteConfig); + this.transactionalConfig.loadModule(NitriteModule.module(new TransactionalStore<>(nitriteStore))); + + this.transactionalConfig.autoConfigure(); + this.transactionalConfig.initialize(); + this.transactionalStore = (TransactionalStore) this.transactionalConfig.getNitriteStore(); this.state = State.Active; } diff --git a/nitrite/src/main/java/org/dizitart/no2/transaction/Session.java b/nitrite/src/main/java/org/dizitart/no2/transaction/Session.java index 74ad2f823..7a8c0a93c 100644 --- a/nitrite/src/main/java/org/dizitart/no2/transaction/Session.java +++ b/nitrite/src/main/java/org/dizitart/no2/transaction/Session.java @@ -4,20 +4,35 @@ import org.dizitart.no2.common.concurrent.LockService; import org.dizitart.no2.exceptions.TransactionException; -import java.io.Closeable; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; /** + * A nitrite transaction session. A session is needed to + * initiate a transaction in nitrite database. + * + *

    + * If a session is closed and the transaction is not committed, + * all opened transactions will get rolled back and all volatile + * data gets discarded for the session. + *

    + * * @author Anindya Chatterjee + * @since 4.0 */ -public class Session implements Closeable { +public class Session implements AutoCloseable { private final Nitrite nitrite; private final AtomicBoolean active; private final LockService lockService; private final Map transactionMap; + /** + * Instantiates a new Session. + * + * @param nitrite the nitrite + * @param lockService the lock service + */ public Session(Nitrite nitrite, LockService lockService) { this.nitrite = nitrite; this.active = new AtomicBoolean(true); @@ -25,6 +40,11 @@ public Session(Nitrite nitrite, LockService lockService) { this.transactionMap = new HashMap<>(); } + /** + * Begins a new transaction. + * + * @return the transaction + */ public Transaction beginTransaction() { checkState(); @@ -43,6 +63,13 @@ public void close() { } } + /** + * Checks state of the session. If the session is not active, + * it will throw a {@link TransactionException}. + * + * @throws TransactionException when the session is not active, + * and a transaction is initiated in this session. + */ public void checkState() { if (!active.get()) { throw new TransactionException("this session is not active"); diff --git a/nitrite/src/main/java/org/dizitart/no2/transaction/State.java b/nitrite/src/main/java/org/dizitart/no2/transaction/State.java index bc4a438b7..39bad9902 100644 --- a/nitrite/src/main/java/org/dizitart/no2/transaction/State.java +++ b/nitrite/src/main/java/org/dizitart/no2/transaction/State.java @@ -1,13 +1,39 @@ package org.dizitart.no2.transaction; /** + * The transaction state. + * * @author Anindya Chatterjee + * @since 4.0 */ public enum State { + /** + * Transaction is active. + */ Active, + + /** + * Transaction is partially committed. + */ PartiallyCommitted, + + /** + * Transaction is fully committed. + */ Committed, + + /** + * Transaction is closed. + */ Closed, + + /** + * Transaction is failed. + */ Failed, + + /** + * Transaction is aborted. + */ Aborted, } diff --git a/nitrite/src/main/java/org/dizitart/no2/transaction/Transaction.java b/nitrite/src/main/java/org/dizitart/no2/transaction/Transaction.java index 77b40e922..5986c6cc7 100644 --- a/nitrite/src/main/java/org/dizitart/no2/transaction/Transaction.java +++ b/nitrite/src/main/java/org/dizitart/no2/transaction/Transaction.java @@ -3,25 +3,66 @@ import org.dizitart.no2.collection.NitriteCollection; import org.dizitart.no2.repository.ObjectRepository; -import java.io.Closeable; - /** + * Represents an ACID transaction on nitrite database. + * * @author Anindya Chatterjee + * @since 4.0 */ -public interface Transaction extends Closeable { +public interface Transaction extends AutoCloseable { + /** + * Gets the transaction id. + * + * @return the id + */ String getId(); + /** + * Gets the current state of the transaction. + * + * @return the state + */ State getState(); + /** + * Gets a {@link NitriteCollection} to perform ACID operations on it. + * + * @param name the name + * @return the collection + */ NitriteCollection getCollection(String name); + /** + * Gets an {@link ObjectRepository} to perform ACID operations on it. + * + * @param the type parameter + * @param type the type + * @return the repository + */ ObjectRepository getRepository(Class type); + /** + * Gets an {@link ObjectRepository} to perform ACID operations on it. + * + * @param the type parameter + * @param type the type + * @param key the key + * @return the repository + */ ObjectRepository getRepository(Class type, String key); + /** + * Completes the transaction and commits the data to the underlying store. + */ void commit(); + /** + * Rolls back the changes. + */ void rollback(); + /** + * Closes this {@link Transaction}. + * */ void close(); } diff --git a/nitrite/src/main/java/org/dizitart/no2/transaction/TransactionContext.java b/nitrite/src/main/java/org/dizitart/no2/transaction/TransactionContext.java index b86598cbe..31ce4b7a7 100644 --- a/nitrite/src/main/java/org/dizitart/no2/transaction/TransactionContext.java +++ b/nitrite/src/main/java/org/dizitart/no2/transaction/TransactionContext.java @@ -10,6 +10,7 @@ /** * @author Anindya Chatterjee + * @since 4.0 */ @Data class TransactionContext implements AutoCloseable { @@ -24,7 +25,7 @@ public TransactionContext() { } @Override - public void close() { + public void close() throws Exception { journal.clear(); nitriteMap.clear(); nitriteMap.close(); diff --git a/nitrite/src/main/java/org/dizitart/no2/transaction/TransactionalConfig.java b/nitrite/src/main/java/org/dizitart/no2/transaction/TransactionalConfig.java index e1e493fc0..ea9f6b391 100644 --- a/nitrite/src/main/java/org/dizitart/no2/transaction/TransactionalConfig.java +++ b/nitrite/src/main/java/org/dizitart/no2/transaction/TransactionalConfig.java @@ -2,46 +2,33 @@ import lombok.extern.slf4j.Slf4j; import org.dizitart.no2.NitriteConfig; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.index.Indexer; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.module.NitriteModule; +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.index.NitriteIndexer; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.common.module.NitriteModule; import org.dizitart.no2.store.NitriteStore; -import java.util.HashMap; -import java.util.Map; - /** * @author Anindya Chatterjee + * @since 4.0 */ @Slf4j class TransactionalConfig extends NitriteConfig { private final NitriteConfig config; - private final TransactionalStore transactionalStore; - private final Map indexerMap; - public TransactionalConfig(NitriteConfig config, TransactionalStore transactionalStore) { + public TransactionalConfig(NitriteConfig config) { + super(); this.config = config; - this.transactionalStore = transactionalStore; - this.indexerMap = new HashMap<>(); } @Override - public Indexer findIndexer(String indexType) { - if (indexerMap.containsKey(indexType)) { - return indexerMap.get(indexType); - } - - try { - Indexer indexer = config.findIndexer(indexType).clone(); - if (indexer != null) { - indexer.initialize(this); - indexerMap.put(indexType, indexer); - } - return indexer; - } catch (CloneNotSupportedException e) { - log.error("Failed to clone indexer", e); - throw new NitriteIOException("error while cloning indexer", e); + public NitriteIndexer findIndexer(String indexType) { + NitriteIndexer nitriteIndexer = pluginManager.getIndexerMap().get(indexType); + if (nitriteIndexer != null) { + nitriteIndexer.initialize(this); + return nitriteIndexer; + } else { + throw new IndexingException("no indexer found for index type " + indexType); } } @@ -52,12 +39,13 @@ public void fieldSeparator(String separator) { @Override public NitriteConfig loadModule(NitriteModule module) { - return config.loadModule(module); + pluginManager.loadModule(module); + return this; } @Override public void autoConfigure() { - config.autoConfigure(); + pluginManager.findAndLoadPlugins(); } @Override @@ -67,6 +55,11 @@ public NitriteMapper nitriteMapper() { @Override public NitriteStore getNitriteStore() { - return transactionalStore; + return pluginManager.getNitriteStore(); + } + + @Override + public void initialize() { + super.initialize(); } } diff --git a/nitrite/src/main/java/org/dizitart/no2/transaction/TransactionalMap.java b/nitrite/src/main/java/org/dizitart/no2/transaction/TransactionalMap.java index 5e97fde74..fc6ba15d6 100644 --- a/nitrite/src/main/java/org/dizitart/no2/transaction/TransactionalMap.java +++ b/nitrite/src/main/java/org/dizitart/no2/transaction/TransactionalMap.java @@ -7,12 +7,13 @@ import org.dizitart.no2.store.memory.InMemoryMap; import java.util.*; -import java.util.concurrent.ConcurrentSkipListSet; +import java.util.concurrent.CopyOnWriteArrayList; import static org.dizitart.no2.common.util.ObjectUtils.deepCopy; /** * @author Anindya Chatterjee + * @since 4.0 */ @SuppressWarnings("SortedCollectionWithNonComparableKeys") class TransactionalMap implements NitriteMap { @@ -56,11 +57,11 @@ public V get(K k) { V result = backingMap.get(k); if (result == null) { result = primary.get(k); - if (result instanceof ConcurrentSkipListSet) { - // create a deep copy of the set so that it does not effect the original one - ConcurrentSkipListSet set = deepCopy((ConcurrentSkipListSet) result); - backingMap.put(k, (V) set); - result = (V) set; + if (result instanceof CopyOnWriteArrayList) { + // create a deep copy of the list so that it does not effect the original one + List list = deepCopy((CopyOnWriteArrayList) result); + backingMap.put(k, (V) list); + result = (V) list; } } @@ -89,7 +90,18 @@ public RecordStream values() { return RecordStream.empty(); } - return RecordStream.fromCombined(primary.values(), backingMap.values()); + return RecordStream.fromIterable(() -> new Iterator() { + private final Iterator> entryIterator = entries().iterator(); + @Override + public boolean hasNext() { + return entryIterator.hasNext(); + } + + @Override + public V next() { + return entryIterator.next().getSecond(); + } + }); } @Override @@ -109,13 +121,13 @@ public V remove(K k) { } @Override - public RecordStream keySet() { + public RecordStream keys() { if (cleared) { return RecordStream.empty(); } - return RecordStream.fromCombined(RecordStream.except(primary.keySet(), tombstones), - backingMap.keySet()); + return RecordStream.fromCombined(RecordStream.except(primary.keys(), tombstones), + backingMap.keys()); } @Override @@ -146,49 +158,12 @@ public V putIfAbsent(K key, V value) { @Override public RecordStream> entries() { - if (cleared) { - return RecordStream.empty(); - } - - return () -> new Iterator>() { - private final Iterator> primaryIterator = primary.entries().iterator(); - private final Iterator> iterator = backingMap.entries().iterator(); - private Pair nextPair; - private boolean nextPairSet = false; - - @Override - public boolean hasNext() { - return nextPairSet || setNextId(); - } - - @Override - public Pair next() { - if (!nextPairSet && !setNextId()) { - throw new NoSuchElementException(); - } - nextPairSet = false; - return nextPair; - } - - private boolean setNextId() { - if (iterator.hasNext()) { - nextPair = iterator.next(); - nextPairSet = true; - return true; - } - - while (primaryIterator.hasNext()) { - final Pair pair = primaryIterator.next(); - if (!tombstones.contains(pair.getFirst())) { - nextPair = pair; - nextPairSet = true; - return true; - } - } + return getStream(primary.entries(), backingMap.entries()); + } - return false; - } - }; + @Override + public RecordStream> reversedEntries() { + return getStream(primary.reversedEntries(), backingMap.reversedEntries()); } @Override @@ -311,4 +286,51 @@ public void close() { backingMap.clear(); tombstones.clear(); } + + private RecordStream> getStream(RecordStream> primaryStream, + RecordStream> backingStream) { + if (cleared) { + return RecordStream.empty(); + } + + return () -> new Iterator>() { + private final Iterator> primaryIterator = primaryStream.iterator(); + private final Iterator> iterator = backingStream.iterator(); + private Pair nextPair; + private boolean nextPairSet = false; + + @Override + public boolean hasNext() { + return nextPairSet || setNextId(); + } + + @Override + public Pair next() { + if (!nextPairSet && !setNextId()) { + throw new NoSuchElementException(); + } + nextPairSet = false; + return nextPair; + } + + private boolean setNextId() { + if (iterator.hasNext()) { + nextPair = iterator.next(); + nextPairSet = true; + return true; + } + + while (primaryIterator.hasNext()) { + final Pair pair = primaryIterator.next(); + if (!tombstones.contains(pair.getFirst())) { + nextPair = pair; + nextPairSet = true; + return true; + } + } + + return false; + } + }; + } } diff --git a/nitrite/src/main/java/org/dizitart/no2/transaction/TransactionalRTree.java b/nitrite/src/main/java/org/dizitart/no2/transaction/TransactionalRTree.java index 63bebcc58..1b96895e2 100644 --- a/nitrite/src/main/java/org/dizitart/no2/transaction/TransactionalRTree.java +++ b/nitrite/src/main/java/org/dizitart/no2/transaction/TransactionalRTree.java @@ -9,6 +9,7 @@ /** * @author Anindya Chatterjee + * @since 4.0 */ class TransactionalRTree implements NitriteRTree { private final Map map; @@ -99,6 +100,21 @@ private SpatialKey getKey(Key key, long id) { key.getMaxX(), key.getMinY(), key.getMaxY()); } + @Override + public void close() { + map.clear(); + } + + @Override + public void clear() { + map.clear(); + } + + @Override + public void drop() { + map.clear(); + } + /* * Copyright 2004-2019 H2 Group. Multiple-Licensed under the MPL 2.0, * and the EPL 1.0 (https://h2database.com/html/license.html). diff --git a/nitrite/src/main/java/org/dizitart/no2/transaction/TransactionalStore.java b/nitrite/src/main/java/org/dizitart/no2/transaction/TransactionalStore.java index 3976d792a..d9478add4 100644 --- a/nitrite/src/main/java/org/dizitart/no2/transaction/TransactionalStore.java +++ b/nitrite/src/main/java/org/dizitart/no2/transaction/TransactionalStore.java @@ -1,6 +1,5 @@ package org.dizitart.no2.transaction; -import org.dizitart.no2.NitriteConfig; import org.dizitart.no2.exceptions.InvalidOperationException; import org.dizitart.no2.index.BoundingBox; import org.dizitart.no2.store.*; @@ -11,6 +10,7 @@ /** * @author Anindya Chatterjee + * @since 4.0 */ class TransactionalStore extends AbstractNitriteStore { private final NitriteStore primaryStore; @@ -49,8 +49,17 @@ public void commit() { } @Override - public void close() { - // nothing to do + public void close() throws Exception { + for (NitriteMap nitriteMap : mapRegistry.values()) { + nitriteMap.close(); + } + + for (NitriteRTree rTree : rTreeRegistry.values()) { + rTree.close(); + } + + mapRegistry.clear(); + rTreeRegistry.clear(); } @Override @@ -82,6 +91,18 @@ public NitriteMap openMap(String mapName, Class keyT return transactionalMap; } + @Override + public void closeMap(String mapName) { + // nothing to close as it is volatile map, moreover, + // removing it form registry means loosing the map + } + + @Override + public void closeRTree(String rTreeName) { + // nothing to close as it is volatile map, moreover, + // removing it form registry means loosing the map + } + @Override public void removeMap(String mapName) { mapRegistry.remove(mapName); @@ -130,9 +151,4 @@ public String getStoreVersion() { public T getStoreConfig() { return null; } - - @Override - public void initialize(NitriteConfig nitriteConfig) { - - } } diff --git a/nitrite/src/main/java/org/dizitart/no2/transaction/UndoEntry.java b/nitrite/src/main/java/org/dizitart/no2/transaction/UndoEntry.java index 41e9b3fe0..a75aab198 100644 --- a/nitrite/src/main/java/org/dizitart/no2/transaction/UndoEntry.java +++ b/nitrite/src/main/java/org/dizitart/no2/transaction/UndoEntry.java @@ -4,6 +4,7 @@ /** * @author Anindya Chatterjee + * @since 4.0 */ @Data class UndoEntry { diff --git a/nitrite/src/test/java/org/dizitart/no2/CollectionFieldIndexTest.java b/nitrite/src/test/java/org/dizitart/no2/CollectionFieldIndexTest.java deleted file mode 100644 index 44ff99c11..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/CollectionFieldIndexTest.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.index.IndexType; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import static org.dizitart.no2.TestUtil.createDb; -import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee - */ -public class CollectionFieldIndexTest { - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - db = createDb(); - } - - @Test - public void testCollection() { - Document doc1 = Document.createDocument("name", "Anindya") - .put("color", new String[]{"red", "green", "blue"}) - .put("books", new Document[]{ - Document.createDocument("name", "Book ABCD") - .put("tag", new String[]{"tag1", "tag2"}), - Document.createDocument("name", "Book EFGH") - .put("tag", new String[]{"tag3", "tag1"}), - Document.createDocument("name", "No Tag") - }); - - Document doc2 = Document.createDocument("name", "Bill") - .put("color", new String[]{"purple", "yellow", "gray"}) - .put("books", new Document[]{ - Document.createDocument("name", "Book abcd") - .put("tag", new String[]{"tag4", "tag5"}), - Document.createDocument("name", "Book wxyz") - .put("tag", new String[]{"tag3", "tag1"}), - Document.createDocument("name", "No Tag 2") - }); - - Document doc3 = Document.createDocument("name", "John") - .put("color", new String[]{"black", "sky", "violet"}) - .put("books", new Document[]{ - Document.createDocument("name", "Book Mnop") - .put("tag", new String[]{"tag6", "tag2"}), - Document.createDocument("name", "Book ghij") - .put("tag", new String[]{"tag3", "tag7"}), - Document.createDocument("name", "No Tag") - }); - - NitriteCollection collection = db.getCollection("test"); - collection.createIndex("color", indexOptions(IndexType.Unique)); - collection.createIndex("books.tag", indexOptions(IndexType.NonUnique)); - collection.createIndex("books.name", indexOptions(IndexType.Fulltext)); - - WriteResult writeResult = collection.insert(doc1, doc2, doc3); - assertEquals(writeResult.getAffectedCount(), 3); - - DocumentCursor documents = collection.find(where("color").eq("red")); - assertTrue(isSimilar(documents.firstOrNull(), doc1, "name", "color", "books")); - - documents = collection.find(where("books.name").text("abcd")); - assertEquals(documents.size(), 2); - - documents = collection.find(where("books.tag").eq("tag2")); - assertEquals(documents.size(), 2); - - documents = collection.find(where("books.tag").eq("tag5")); - assertEquals(documents.size(), 1); - - documents = collection.find(where("books.tag").eq("tag10")); - assertEquals(documents.size(), 0); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/CustomFilterTest.java b/nitrite/src/test/java/org/dizitart/no2/CustomFilterTest.java deleted file mode 100644 index 518a1b56b..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/CustomFilterTest.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.dizitart.no2.collection.BaseCollectionTest; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.index.IndexType; -import org.junit.Test; - -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class CustomFilterTest extends BaseCollectionTest { - - @Test - public void testCustomFilter() { - insert(); - collection.createIndex("firstName", indexOptions(IndexType.NonUnique)); - DocumentCursor cursor = collection.find(element -> element.getSecond().get("firstName", String.class) - .equalsIgnoreCase("FN1")); - - assertEquals(cursor.size(), 1); - assertEquals(cursor.firstOrNull().get("firstName"), "fn1"); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/DbTestOperations.java b/nitrite/src/test/java/org/dizitart/no2/DbTestOperations.java deleted file mode 100644 index ef5cfd217..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/DbTestOperations.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.index.IndexType; -import org.junit.Rule; - -import java.io.File; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.*; - -import static org.dizitart.no2.TestUtil.isSorted; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee. - */ -public class DbTestOperations { - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - public static String getRandomTempDbFile() { - String dataDir = System.getProperty("java.io.tmpdir") + File.separator + "nitrite" + File.separator + "data"; - File file = new File(dataDir); - if (!file.exists()) { - assertTrue(file.mkdirs()); - } - return file.getPath() + File.separator + UUID.randomUUID().toString() + ".db"; - } - - void createDb() { - db = TestUtil.createDb(); - db.close(); - } - - void writeCollection() { - NitriteCollection collection; - - db = TestUtil.createDb(); - - collection = db.getCollection("test"); - collection.remove(ALL); - db.close(); - } - - void writeIndex() { - NitriteCollection collection; - - db = TestUtil.createDb(); - - collection = db.getCollection("test"); - collection.remove(ALL); - collection.createIndex("body", indexOptions(IndexType.Fulltext)); - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - db.close(); - } - - void insertInCollection() throws ParseException { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); - - Document doc1 = createDocument("firstName", "fn1") - .put("lastName", "ln1") - .put("birthDay", simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) - .put("data", new byte[]{1, 2, 3}) - .put("body", "a quick brown fox jump over the lazy dog"); - Document doc2 = createDocument("firstName", "fn2") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2010-06-12T16:02:48.440Z")) - .put("data", new byte[]{3, 4, 3}) - .put("body", "quick hello world from nitrite"); - Document doc3 = createDocument("firstName", "fn3") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2014-04-17T16:02:48.440Z")) - .put("data", new byte[]{9, 4, 8}) - .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + - "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); - - NitriteCollection collection; - - db = TestUtil.createDb(); - - collection = db.getCollection("test"); - - WriteResult result = collection.insert(doc1, doc2, doc3); - assertEquals(result.getAffectedCount(), 3); - - db.commit(); - db.close(); - } - - void readCollection() throws ParseException { - NitriteCollection collection; - - db = TestUtil.createDb(); - - collection = db.getCollection("test"); - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").gt(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").gte(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lt(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lte(new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").lt(new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").gt(new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").gte(new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").lte(new Date()).and(where("firstName").eq("fn1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte(new Date()).or(where("firstName").eq("fn12"))); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1")) - .not()); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").eq((byte) 4)); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").lt(4)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("firstName").notIn("fn1", "fn2")); - assertEquals(cursor.size(), 1); - - collection.createIndex("birthDay", indexOptions(IndexType.Unique)); - cursor = collection.find().sort("birthDay", SortOrder.Descending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, false)); - - cursor = collection.find(where("body").text("Lorem")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("body").text("quick")); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("body").text("nosql")); - assertEquals(cursor.size(), 0); - - db.close(); - } - - void deleteDb() { - if (db != null && !db.isClosed()) { - db.close(); - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/DocumentMetadataTest.java b/nitrite/src/test/java/org/dizitart/no2/DocumentMetadataTest.java deleted file mode 100644 index 3a912de78..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/DocumentMetadataTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.dizitart.no2.collection.BaseCollectionTest; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.events.EventType; -import org.junit.Test; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee. - */ -public class DocumentMetadataTest extends BaseCollectionTest { - @Test - public void testTimeStamp() { - Document document = createDocument("test_key", "test_value"); - assertEquals(document.getRevision().intValue(), 0); - assertEquals(document.getLastModifiedSinceEpoch().longValue(), 0L); - - collection.insert(document); - document = collection.find().firstOrNull(); - - assertEquals(document.getRevision().intValue(), 1); - assertTrue(document.getLastModifiedSinceEpoch() > 0); - - long previous = document.getRevision(); - - DocumentCursor cursor = collection.find(where("test_key").eq("test_value")); - document = cursor.firstOrNull(); - document.put("another_key", "another_value"); - - collection.update(document); - cursor = collection.find(where("test_key").eq("test_value")); - document = cursor.firstOrNull(); - - assertTrue(document.getRevision() > previous); - - final long time = document.getRevision(); - final Document removed = document; - - collection.subscribe(changeInfo -> { - if (changeInfo.getEventType() == EventType.Remove) { - assertTrue(removed.getRevision() > time); - } - }); - - collection.remove(document); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/EventTypeTest.java b/nitrite/src/test/java/org/dizitart/no2/EventTypeTest.java deleted file mode 100644 index 4fd93bf08..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/EventTypeTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.dizitart.no2.collection.events.EventType; -import org.junit.Rule; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class EventTypeTest { - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testValueOf() { - assertEquals(EventType.valueOf("Insert"), EventType.Insert); - assertEquals(EventType.valueOf("Update"), EventType.Update); - assertEquals(EventType.valueOf("Remove"), EventType.Remove); - assertEquals(EventType.valueOf("IndexStart"), EventType.IndexStart); - assertEquals(EventType.valueOf("IndexEnd"), EventType.IndexEnd); - - assertEquals(EventType.values().length, 5); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/IndexEntryTest.java b/nitrite/src/test/java/org/dizitart/no2/IndexEntryTest.java deleted file mode 100644 index f6ae305a8..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/IndexEntryTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.dizitart.no2.index.IndexEntry; -import org.dizitart.no2.index.IndexType; -import org.junit.Rule; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class IndexEntryTest { - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testIndexEquals() { - IndexEntry index = new IndexEntry(IndexType.Fulltext, "test", "testColl"); - IndexEntry index2 = new IndexEntry(IndexType.Fulltext, "test", "testColl"); - assertEquals(index, index2); - } - - @Test - public void testIndexCompare() { - IndexEntry index = new IndexEntry(IndexType.Fulltext, "test", "testColl"); - IndexEntry index2 = new IndexEntry(IndexType.Fulltext, "test", "testColl"); - - assertEquals(index.toString(), "IndexEntry(indexType=Fulltext, field=test, collectionName=testColl)"); - assertEquals(index.compareTo(index2), 0); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/MultiThreadedTest.java b/nitrite/src/test/java/org/dizitart/no2/MultiThreadedTest.java deleted file mode 100644 index 12128d8d6..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/MultiThreadedTest.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.concurrent.ThreadPoolManager; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.util.Date; -import java.util.Random; -import java.util.UUID; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.TestUtil.createDb; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - - -/** - * @author Anindya Chatterjee. - */ -public class MultiThreadedTest { - private static final String fileName = getRandomTempDbFile(); - private NitriteCollection collection; - private final int threadCount = 20; - private final CountDownLatch latch = new CountDownLatch(threadCount); - private final int iterationCount = 100; - private final Random generator = new Random(); - private final AtomicInteger docCounter = new AtomicInteger(0); - private ExecutorService executor = ThreadPoolManager.getThreadPool(threadCount, "MultiThreadedTest"); - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testOperations() throws InterruptedException { - db = createDb(); - - collection = db.getCollection("test"); - collection.remove(Filter.ALL); - collection.createIndex("unixTime", IndexOptions.indexOptions(IndexType.Unique)); - db.commit(); - - for (int i = 0; i < threadCount; i++) { - executor.submit(() -> { - for (int j = 0; j < iterationCount; j++) { - try { - Document document = generate(); - collection.insert(document); - - if (j == iterationCount / 2 - && !collection.hasIndex("text") - && !collection.hasIndex("date")) { - collection.createIndex("text", IndexOptions.indexOptions(IndexType.Fulltext)); - collection.createIndex("date", IndexOptions.indexOptions(IndexType.NonUnique)); - } - - long unixTime = (long) document.get("unixTime"); - DocumentCursor cursor = collection.find(where("unixTime").eq(unixTime)); - assertTrue(cursor.size() >= 0); - - if (collection.hasIndex("text") && !collection.isIndexing("text")) { - String textData = (String) document.get("text"); - cursor = collection.find(where("text").text(textData)); - assertTrue(cursor.size() >= 0); - } - - assertTrue(collection.hasIndex("unixTime")); - } catch (Throwable e) { - System.out.println("Exception at thread " + - Thread.currentThread().getName() + " with iteration " + j); - e.printStackTrace(); - } - } - latch.countDown(); - }); - } - - latch.await(); - - db.commit(); - - assertTrue(collection.hasIndex("text")); - assertTrue(collection.hasIndex("date")); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), docCounter.get()); - - cursor = collection.find(where("unixTime").gt(1L)); - assertEquals(cursor.size(), docCounter.get()); - - db.close(); - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - - if (executor != null && !executor.isShutdown()) { - executor.shutdown(); - executor = null; - } - } - - private synchronized Document generate() { - Document document = createDocument("unixTime", System.nanoTime() + docCounter.incrementAndGet()); - byte[] blob = new byte[1024]; - generator.nextBytes(blob); - document.put("blob", blob); - document.put("text", UUID.randomUUID().toString().replaceAll("-", " ")); - document.put("date", new Date()); - return document; - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/NitriteBuilderTest.java b/nitrite/src/test/java/org/dizitart/no2/NitriteBuilderTest.java index 167920bed..59d877268 100644 --- a/nitrite/src/test/java/org/dizitart/no2/NitriteBuilderTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/NitriteBuilderTest.java @@ -1,45 +1,53 @@ /* - * Copyright (c) 2017-2020. Nitrite author or authors. + * Copyright (c) 2017-2021 Nitrite author or authors. * * Licensed 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 + * 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.dizitart.no2; import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.FindPlan; import org.dizitart.no2.collection.NitriteCollection; import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.exceptions.SecurityException; -import org.dizitart.no2.index.Indexer; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.module.PluginManager; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.common.FieldValues; +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.common.module.NitriteModule; +import org.dizitart.no2.common.module.NitritePlugin; +import org.dizitart.no2.common.module.PluginManager; +import org.dizitart.no2.exceptions.NitriteSecurityException; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.NitriteIndexer; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.migration.Migration; import org.dizitart.no2.store.NitriteStore; import org.dizitart.no2.store.StoreConfig; +import org.dizitart.no2.store.memory.InMemoryConfig; import org.junit.After; import org.junit.Rule; import org.junit.Test; +import java.util.HashSet; +import java.util.LinkedHashSet; + import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.common.module.NitriteModule.module; import static org.dizitart.no2.common.util.StringUtils.isNullOrEmpty; -import static org.dizitart.no2.module.NitriteModule.module; import static org.junit.Assert.*; +import static org.mockito.Mockito.*; -/** - * @author Anindya Chatterjee. - */ public class NitriteBuilderTest { private Nitrite db; @@ -55,6 +63,144 @@ public void cleanup() { } } + @Test + public void testConstructor() { + NitriteConfig nitriteConfig = (new NitriteBuilder()).getNitriteConfig(); + assertTrue(nitriteConfig.getMigrations().isEmpty()); + assertFalse(nitriteConfig.configured); + assertEquals(1, nitriteConfig.getSchemaVersion().intValue()); + assertNull(nitriteConfig.getNitriteStore()); + PluginManager pluginManager = nitriteConfig.getPluginManager(); + assertSame(nitriteConfig, pluginManager.getNitriteConfig()); + assertTrue(pluginManager.getIndexerMap().isEmpty()); + } + + @Test + public void testFieldSeparator() { + NitriteBuilder builderResult = Nitrite.builder(); + assertSame(builderResult, builderResult.fieldSeparator("Separator")); + + db = Nitrite.builder() + .fieldSeparator("::") + .openOrCreate(); + + Document document = createDocument("firstName", "John") + .put("colorCodes", new Document[]{createDocument("color", "Red"), createDocument("color", "Green")}) + .put("address", createDocument("street", "ABCD Road")); + + String street = document.get("address::street", String.class); + assertEquals("ABCD Road", street); + + // use default separator, it should return null + street = document.get("address.street", String.class); + assertNull(street); + + assertEquals(document.get("colorCodes::1::color"), "Green"); + } + + @Test + public void testLoadModule() { + NitriteBuilder builderResult = Nitrite.builder(); + NitriteModule nitriteModule = mock(NitriteModule.class); + when(nitriteModule.plugins()).thenReturn(new HashSet()); + assertSame(builderResult, builderResult.loadModule(nitriteModule)); + verify(nitriteModule, times(2)).plugins(); + } + + @Test + public void testAddMigrations() { + NitriteBuilder builderResult = Nitrite.builder(); + assertSame(builderResult, builderResult.addMigrations(null, null, null)); + } + + @Test + public void testAddMigrations2() { + NitriteBuilder builderResult = Nitrite.builder(); + Migration migration = mock(Migration.class); + when(migration.getEndVersion()).thenReturn(1); + when(migration.getStartVersion()).thenReturn(1); + assertSame(builderResult, builderResult.addMigrations(migration, null, null)); + verify(migration).getEndVersion(); + verify(migration).getStartVersion(); + } + + @Test + public void testSchemaVersion() { + NitriteBuilder builderResult = Nitrite.builder(); + assertSame(builderResult, builderResult.schemaVersion(1)); + } + + @Test + public void testOpenOrCreate() { + Nitrite actualOpenOrCreateResult = Nitrite.builder().openOrCreate("janedoe", "iloveyou"); + PluginManager pluginManager = actualOpenOrCreateResult.getConfig().getPluginManager(); + NitriteStore store = actualOpenOrCreateResult.getStore(); + assertFalse(actualOpenOrCreateResult.isClosed()); + assertFalse(store.isClosed()); + assertSame(store, pluginManager.getNitriteStore()); + assertTrue(pluginManager.getNitriteMapper() instanceof org.dizitart.no2.common.mapper.MappableMapper); + } + + @Test + public void testOpenOrCreate2() { + Nitrite actualOpenOrCreateResult = Nitrite.builder().openOrCreate(); + assertFalse(actualOpenOrCreateResult.isClosed()); + NitriteConfig config = actualOpenOrCreateResult.getConfig(); + assertTrue(config.configured); + NitriteStore store = actualOpenOrCreateResult.getStore(); + assertTrue(store.getRepositoryRegistry().isEmpty()); + assertFalse(store.isClosed()); + PluginManager pluginManager = config.getPluginManager(); + assertEquals(3, pluginManager.getIndexerMap().size()); + assertTrue(pluginManager.getNitriteMapper() instanceof org.dizitart.no2.common.mapper.MappableMapper); + assertTrue(store.getCatalog().getKeyedRepositoryNames().isEmpty()); + assertSame(store, pluginManager.getNitriteStore()); + assertTrue(((InMemoryConfig) store.getStoreConfig()).eventListeners().isEmpty()); + } + + @Test + public void testOpenOrCreate3() { + Nitrite actualOpenOrCreateResult = Nitrite.builder().openOrCreate("janedoe", "iloveyou"); + assertFalse(actualOpenOrCreateResult.isClosed()); + NitriteConfig config = actualOpenOrCreateResult.getConfig(); + assertTrue(config.configured); + NitriteStore store = actualOpenOrCreateResult.getStore(); + assertTrue(store.getRepositoryRegistry().isEmpty()); + assertFalse(store.isClosed()); + PluginManager pluginManager = config.getPluginManager(); + assertEquals(3, pluginManager.getIndexerMap().size()); + assertTrue(pluginManager.getNitriteMapper() instanceof org.dizitart.no2.common.mapper.MappableMapper); + assertTrue(store.getCatalog().getKeyedRepositoryNames().isEmpty()); + assertSame(store, pluginManager.getNitriteStore()); + assertTrue(((InMemoryConfig) store.getStoreConfig()).eventListeners().isEmpty()); + } + + @Test(expected = NitriteSecurityException.class) + public void testOpenOrCreate4() { + NitriteBuilder builderResult = Nitrite.builder(); + builderResult.openOrCreate("", "iloveyou"); + NitriteConfig nitriteConfig = builderResult.getNitriteConfig(); + PluginManager pluginManager = nitriteConfig.getPluginManager(); + assertEquals(3, pluginManager.getIndexerMap().size()); + NitriteStore nitriteStore = nitriteConfig.getNitriteStore(); + assertSame(nitriteStore, pluginManager.getNitriteStore()); + assertTrue(pluginManager.getNitriteMapper() instanceof org.dizitart.no2.common.mapper.MappableMapper); + assertFalse(nitriteStore.isClosed()); + assertTrue(((InMemoryConfig) nitriteStore.getStoreConfig()).eventListeners().isEmpty()); + } + + @Test(expected = NitriteSecurityException.class) + public void testOpenOrCreate5() { + NitriteBuilder builderResult = Nitrite.builder(); + builderResult.openOrCreate("", "iloveyou"); + NitriteConfig nitriteConfig = builderResult.getNitriteConfig(); + PluginManager pluginManager = nitriteConfig.getPluginManager(); + NitriteStore nitriteStore = nitriteConfig.getNitriteStore(); + assertFalse(nitriteStore.isClosed()); + assertSame(nitriteStore, pluginManager.getNitriteStore()); + assertTrue(pluginManager.getNitriteMapper() instanceof org.dizitart.no2.common.mapper.MappableMapper); + } + @Test public void testConfig() { @@ -108,62 +254,19 @@ public void testNitriteMapper() { assertNotNull(config.nitriteMapper()); } - @Test(expected = SecurityException.class) + @Test(expected = NitriteSecurityException.class) public void testOpenOrCreateNullUserId() { NitriteBuilder builder = Nitrite.builder(); builder.openOrCreate(null, "abcd"); } - @Test - public void testOpenOrCreate() { - Nitrite actualOpenOrCreateResult = Nitrite.builder().openOrCreate("janedoe", "iloveyou"); - PluginManager pluginManager = actualOpenOrCreateResult.getConfig().getPluginManager(); - NitriteStore store = actualOpenOrCreateResult.getStore(); - assertFalse(actualOpenOrCreateResult.isClosed()); - assertFalse(store.isClosed()); - assertSame(store, pluginManager.getNitriteStore()); - assertTrue(pluginManager.getNitriteMapper() instanceof org.dizitart.no2.mapper.MappableMapper); - } - - @Test(expected = SecurityException.class) - public void testOpenOrCreate2() { - NitriteBuilder builderResult = Nitrite.builder(); - builderResult.openOrCreate("", "iloveyou"); - NitriteConfig nitriteConfig = builderResult.getNitriteConfig(); - PluginManager pluginManager = nitriteConfig.getPluginManager(); - NitriteStore nitriteStore = nitriteConfig.getNitriteStore(); - assertFalse(nitriteStore.isClosed()); - assertSame(nitriteStore, pluginManager.getNitriteStore()); - assertTrue(pluginManager.getNitriteMapper() instanceof org.dizitart.no2.mapper.MappableMapper); - } - - @Test(expected = SecurityException.class) + @Test(expected = NitriteSecurityException.class) public void testOpenOrCreateNullPassword() { NitriteBuilder builder = Nitrite.builder(); builder.openOrCreate("abcd", null); } - @Test - public void testFieldSeparator() { - db = Nitrite.builder() - .fieldSeparator("::") - .openOrCreate(); - - Document document = createDocument("firstName", "John") - .put("colorCodes", new Document[]{createDocument("color", "Red"), createDocument("color", "Green")}) - .put("address", createDocument("street", "ABCD Road")); - - String street = document.get("address::street", String.class); - assertEquals("ABCD Road", street); - - // use default separator, it should return null - street = document.get("address.street", String.class); - assertNull(street); - - assertEquals(document.get("colorCodes::1::color"), "Green"); - } - - private static class CustomIndexer implements Indexer { + private static class CustomIndexer implements NitriteIndexer { @Override public String getIndexType() { @@ -171,30 +274,31 @@ public String getIndexType() { } @Override - public void writeIndex(NitriteMap collection, NitriteId nitriteId, String field, Object fieldValue) { + public void validateIndex(Fields fields) { } @Override - public void removeIndex(NitriteMap collection, NitriteId nitriteId, String field, Object fieldValue) { + public void dropIndex(IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig) { } @Override - public void updateIndex(NitriteMap collection, NitriteId nitriteId, String field, Object newValue, Object oldValue) { + public void writeIndexEntry(FieldValues fieldValues, IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig) { } @Override - public void dropIndex(NitriteMap collection, String field) { + public void removeIndexEntry(FieldValues fieldValues, IndexDescriptor indexDescriptor, NitriteConfig nitriteConfig) { } @Override - public Indexer clone() throws CloneNotSupportedException { + public LinkedHashSet findByFilter(FindPlan findPlan, NitriteConfig nitriteConfig) { return null; } + @Override public void initialize(NitriteConfig nitriteConfig) { @@ -224,59 +328,5 @@ public void initialize(NitriteConfig nitriteConfig) { } } - @Index(value = "longValue") - private static class TestObject implements Mappable { - private String stringValue; - private Long longValue; - - public TestObject() { - } - - public TestObject(String stringValue, Long longValue) { - this.longValue = longValue; - this.stringValue = stringValue; - } - - @Override - public Document write(NitriteMapper mapper) { - return createDocument("stringValue", stringValue) - .put("longValue", longValue); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - if (document != null) { - this.stringValue = document.get("stringValue", String.class); - this.longValue = document.get("longValue", Long.class); - } - } - } - - @Index(value = "longValue") - private static class TestObject2 implements Mappable { - private String stringValue; - private Long longValue; - - public TestObject2() { - } - - public TestObject2(String stringValue, Long longValue) { - this.longValue = longValue; - this.stringValue = stringValue; - } - - @Override - public Document write(NitriteMapper mapper) { - return createDocument("stringValue", stringValue) - .put("longValue", longValue); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - if (document != null) { - this.stringValue = document.get("stringValue", String.class); - this.longValue = document.get("longValue", Long.class); - } - } - } } + diff --git a/nitrite/src/test/java/org/dizitart/no2/NitriteConfigTest.java b/nitrite/src/test/java/org/dizitart/no2/NitriteConfigTest.java new file mode 100644 index 000000000..684d4840e --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/NitriteConfigTest.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2; + +import org.dizitart.no2.common.module.NitriteModule; +import org.dizitart.no2.common.module.NitritePlugin; +import org.dizitart.no2.common.module.PluginManager; +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.exceptions.NitriteIOException; +import org.dizitart.no2.migration.Migration; +import org.dizitart.no2.store.NitriteStore; +import org.dizitart.no2.store.memory.InMemoryConfig; +import org.junit.Test; + +import java.util.HashSet; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class NitriteConfigTest { + @Test + public void testConstructor() { + NitriteConfig actualNitriteConfig = new NitriteConfig(); + assertTrue(actualNitriteConfig.getMigrations().isEmpty()); + assertFalse(actualNitriteConfig.configured); + assertEquals(1, actualNitriteConfig.getSchemaVersion().intValue()); + assertNull(actualNitriteConfig.getNitriteStore()); + PluginManager pluginManager = actualNitriteConfig.getPluginManager(); + assertSame(actualNitriteConfig, pluginManager.getNitriteConfig()); + assertTrue(pluginManager.getIndexerMap().isEmpty()); + } + + @Test + public void testFieldSeparator() { + // TODO: This test is incomplete. + // Reason: No meaningful assertions found. + // To help Diffblue Cover to find assertions, please add getters to the + // class under test that return fields written by the method under test. + // See https://diff.blue/R004 + + (new NitriteConfig()).fieldSeparator("Separator"); + } + + @Test + public void testLoadModule() { + NitriteConfig nitriteConfig = new NitriteConfig(); + NitriteModule nitriteModule = mock(NitriteModule.class); + when(nitriteModule.plugins()).thenReturn(new HashSet()); + assertSame(nitriteConfig, nitriteConfig.loadModule(nitriteModule)); + verify(nitriteModule, times(2)).plugins(); + } + + @Test + public void testAddMigration() { + NitriteConfig nitriteConfig = new NitriteConfig(); + assertSame(nitriteConfig, nitriteConfig.addMigration(null)); + } + + @Test + public void testAddMigration2() { + NitriteConfig nitriteConfig = new NitriteConfig(); + Migration migration = mock(Migration.class); + when(migration.getEndVersion()).thenReturn(1); + when(migration.getStartVersion()).thenReturn(1); + assertSame(nitriteConfig, nitriteConfig.addMigration(migration)); + verify(migration).getEndVersion(); + verify(migration).getStartVersion(); + } + + @Test + public void testAddMigration3() { + NitriteConfig nitriteConfig = new NitriteConfig(); + Migration migration = mock(Migration.class); + when(migration.getEndVersion()).thenReturn(4); + when(migration.getStartVersion()).thenReturn(1); + assertSame(nitriteConfig, nitriteConfig.addMigration(migration)); + verify(migration).getEndVersion(); + verify(migration).getStartVersion(); + } + + @Test + public void testAddMigration4() { + NitriteConfig nitriteConfig = new NitriteConfig(); + Migration migration = mock(Migration.class); + when(migration.getEndVersion()).thenReturn(1); + when(migration.getStartVersion()).thenReturn(4); + assertSame(nitriteConfig, nitriteConfig.addMigration(migration)); + verify(migration).getEndVersion(); + verify(migration).getStartVersion(); + } + + @Test + public void testSchemaVersion() { + NitriteConfig nitriteConfig = new NitriteConfig(); + NitriteConfig actualSchemaVersionResult = nitriteConfig.schemaVersion(1); + assertSame(nitriteConfig, actualSchemaVersionResult); + assertEquals(1, actualSchemaVersionResult.getSchemaVersion().intValue()); + } + + @Test + public void testAutoConfigure() { + NitriteConfig nitriteConfig = new NitriteConfig(); + nitriteConfig.autoConfigure(); + PluginManager pluginManager = nitriteConfig.getPluginManager(); + assertEquals(3, pluginManager.getIndexerMap().size()); + NitriteStore nitriteStore = nitriteConfig.getNitriteStore(); + assertSame(nitriteStore, pluginManager.getNitriteStore()); + assertTrue(pluginManager.getNitriteMapper() instanceof org.dizitart.no2.common.mapper.MappableMapper); + assertFalse(nitriteStore.isClosed()); + assertTrue(((InMemoryConfig) nitriteStore.getStoreConfig()).eventListeners().isEmpty()); + } + + @Test + public void testFindIndexer() { + assertThrows(IndexingException.class, () -> (new NitriteConfig()).findIndexer("Index Type")); + } + + @Test + public void testNitriteMapper() { + assertNull((new NitriteConfig()).nitriteMapper()); + } + + @Test + public void testGetNitriteStore() { + assertNull((new NitriteConfig()).getNitriteStore()); + } + + @Test(expected = NitriteIOException.class) + public void testInitialize() { + NitriteConfig nitriteConfig = new NitriteConfig(); + nitriteConfig.initialize(); + assertTrue(nitriteConfig.configured); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/NitriteCorruptedTest.java b/nitrite/src/test/java/org/dizitart/no2/NitriteCorruptedTest.java deleted file mode 100644 index 408c171d0..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/NitriteCorruptedTest.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.concurrent.ThreadPoolManager; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.util.concurrent.ExecutorService; - -import static org.dizitart.no2.TestUtil.createDb; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee - */ -public class NitriteCorruptedTest { - private Nitrite db; - private NitriteCollection collection; - private Thread thread; - private final ExecutorService dbPool = ThreadPoolManager.getThreadPool(Runtime.getRuntime().availableProcessors(), - "NitriteCorruptedTest"); - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - db = createDb(); - - collection = db.getCollection("test"); - collection.remove(ALL); - - thread = new Thread(() -> { - for (int i = 0; i < 50000; i++) { - - // Interruption Guard - if (Thread.interrupted()) { - break; - } - - Document doc1 = createDocument(String.valueOf(System.currentTimeMillis()), "fn1") - .put("lastName", "ln1") - .put("data", new byte[]{1, 2, 3}) - .put("body", "a quick brown fox jump over the lazy dog"); - - // Separate user thread from Db write thread - dbPool.submit(() -> collection.insert(doc1)); - } - }); - } - - @After - public void tearDown() { - if (collection.isOpen()) { - collection.remove(ALL); - collection.close(); - } - db.close(); - } - - @Test(timeout = 10000) - public void issue118() throws InterruptedException { - thread.start(); - Thread.sleep(10); - thread.interrupt(); - Thread.sleep(500); - assertTrue(collection.isOpen()); - assertFalse(db.isClosed()); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/NitriteDatabaseTest.java b/nitrite/src/test/java/org/dizitart/no2/NitriteDatabaseTest.java new file mode 100644 index 000000000..ea64480e6 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/NitriteDatabaseTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2; + +import org.dizitart.no2.exceptions.NitriteIOException; +import org.dizitart.no2.exceptions.NitriteSecurityException; +import org.dizitart.no2.store.memory.InMemoryStoreModule; +import org.junit.Test; + +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +public class NitriteDatabaseTest { + @Test + public void testConstructor() { + NitriteConfig nitriteConfig = new NitriteConfig(); + nitriteConfig.loadModule(new InMemoryStoreModule()); + new NitriteDatabase("janedoe", "iloveyou", nitriteConfig); + assertTrue(nitriteConfig.configured); + } + + @Test + public void testConstructor2() { + assertThrows(NitriteSecurityException.class, () -> new NitriteDatabase("", "iloveyou", new NitriteConfig())); + } + + @Test + public void testConstructor3() { + assertThrows(NitriteSecurityException.class, () -> new NitriteDatabase("janedoe", "", new NitriteConfig())); + } + + @Test + public void testConstructor4() { + assertThrows(NitriteIOException.class, () -> new NitriteDatabase("janedoe", "iloveyou", null)); + } + + @Test(expected = NitriteIOException.class) + public void testConstructor5() { + NitriteConfig nitriteConfig = new NitriteConfig(); + new NitriteDatabase(nitriteConfig); + assertTrue(nitriteConfig.configured); + } + + @Test + public void testConstructor6() { + assertThrows(NitriteIOException.class, () -> new NitriteDatabase(null)); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/NitriteIdTest.java b/nitrite/src/test/java/org/dizitart/no2/NitriteIdTest.java deleted file mode 100644 index 2a516c60d..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/NitriteIdTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.exceptions.InvalidIdException; -import org.junit.Rule; -import org.junit.Test; - -import static org.junit.Assert.*; - -public class NitriteIdTest { - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testLimit() { - NitriteId one = NitriteId.createId(Long.toString(Long.MAX_VALUE)); - NitriteId two = NitriteId.createId(Long.toString(Long.MIN_VALUE)); - assertEquals(one.compareTo(two), 1); - } - - @Test - public void testHashEquals() { - NitriteId one = NitriteId.createId("1"); - NitriteId two = NitriteId.createId("1"); - - assertEquals(one, two); - assertEquals(one.hashCode(), two.hashCode()); - - NitriteId third = NitriteId.createId("2"); - assertNotEquals(one, third); - assertNotEquals(one.hashCode(), third.hashCode()); - } - - @Test - public void testCompare() { - NitriteId one = NitriteId.createId("1"); - NitriteId two = NitriteId.createId("2"); - NitriteId three = NitriteId.createId("3"); - - assertEquals(one.compareTo(two), -1); - assertEquals(three.compareTo(one), 1); - - one = NitriteId.createId("10"); - two = NitriteId.createId("20"); - assertEquals(one.compareTo(two), -1); - - one = NitriteId.newId(); - two = NitriteId.newId(); - - assertFalse(one.compareTo(two) == 0); - } - - @Test(expected = InvalidIdException.class) - public void testToString() { - NitriteId nullId = NitriteId.createId(null); - assertNotEquals(nullId.toString(), ""); - } - - @Test(expected = InvalidIdException.class) - public void testCompareNull() { - NitriteId first = NitriteId.newId(); - NitriteId second = NitriteId.createId(null); - assertEquals(first.compareTo(second), 1); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/NitriteSecurityTest.java b/nitrite/src/test/java/org/dizitart/no2/NitriteSecurityTest.java deleted file mode 100644 index 75a1a936b..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/NitriteSecurityTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import org.dizitart.no2.collection.NitriteCollection; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import static org.dizitart.no2.TestUtil.createDb; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class NitriteSecurityTest { - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testInMemory() { - db = createDb("test-user", "test-password"); - NitriteCollection dbCollection = db.getCollection("test"); - dbCollection.insert(createDocument("test", "test")); - db.commit(); - assertEquals(dbCollection.find().size(), 1); - db.close(); - - db = createDb(); - dbCollection = db.getCollection("test"); - assertEquals(dbCollection.find().size(), 0); - db.close(); - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/NitriteStressTest.java b/nitrite/src/test/java/org/dizitart/no2/NitriteStressTest.java deleted file mode 100644 index 29e1dddc7..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/NitriteStressTest.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Id; -import org.junit.Rule; -import org.junit.Test; -import uk.co.jemos.podam.api.PodamFactory; -import uk.co.jemos.podam.api.PodamFactoryImpl; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlSchemaType; -import java.util.ArrayList; -import java.util.List; - -import static org.dizitart.no2.TestUtil.createDb; - - -/** - * @author Anindya Chatterjee - */ -public class NitriteStressTest { - private static final int TEST_SET_COUNT = 15000; - private final PodamFactory podamFactory = new PodamFactoryImpl(); - - @Rule - public Retry retry = new Retry(3); - - @Test - public void stressTest() { - Nitrite database = createDb(); - ObjectRepository testRepository = database.getRepository(TestDto.class); - testRepository.createIndex("lastName", IndexOptions.indexOptions(IndexType.Fulltext)); - testRepository.createIndex("birthDate", IndexOptions.indexOptions(IndexType.NonUnique)); - - int counter = 0; - try { - for (TestDto testDto : createTestSet()) { - testRepository.insert(testDto); - counter++; - } - } catch (Throwable t) { - System.err.println("Crashed after " + counter + " records"); - throw t; - } - } - - private List createTestSet() { - List testData = new ArrayList<>(); - for (int i = 0; i < TEST_SET_COUNT; i++) { - TestDto testRecords = podamFactory.manufacturePojo(TestDto.class); - testData.add(testRecords); - } - return testData; - } - - @Data - public static class TestDto implements Mappable { - - @XmlElement( - name = "StudentNumber", - required = true - ) - @Id - protected String studentNumber; - - @XmlElement( - name = "LastName", - required = true - ) - protected String lastName; - - @XmlElement( - name = "Prefixes" - ) - protected String prefixes; - - @XmlElement( - name = "Initials", - required = true - ) - protected String initials; - - @XmlElement( - name = "FirstNames" - ) - protected String firstNames; - @XmlElement( - name = "Nickname" - ) - protected String nickName; - - @XmlElement( - name = "BirthDate", - required = true - ) - @XmlSchemaType( - name = "date" - ) - protected String birthDate; - - - public TestDto() { - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("studentNumber", studentNumber) - .put("lastName", lastName) - .put("prefixes", prefixes) - .put("initials", initials) - .put("firstNames", firstNames) - .put("nickName", nickName) - .put("birthDate", birthDate); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - studentNumber = document.get("studentNumber", String.class); - lastName = document.get("lastName", String.class); - prefixes = document.get("prefixes", String.class); - initials = document.get("initials", String.class); - firstNames = document.get("firstNames", String.class); - nickName = document.get("nickName", String.class); - birthDate = document.get("birthDate", String.class); - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/NitriteTest.java b/nitrite/src/test/java/org/dizitart/no2/NitriteTest.java deleted file mode 100644 index f5d18940e..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/NitriteTest.java +++ /dev/null @@ -1,431 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.UpdateOptions; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.common.concurrent.ThreadPoolManager; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import uk.co.jemos.podam.api.PodamFactory; -import uk.co.jemos.podam.api.PodamFactoryImpl; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Locale; -import java.util.Random; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; - -import static org.dizitart.no2.TestUtil.createDb; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.common.Constants.INTERNAL_NAME_SEPARATOR; -import static org.dizitart.no2.common.Constants.META_MAP_NAME; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class NitriteTest { - @Rule - public Retry retry = new Retry(3); - private Nitrite db; - private NitriteCollection collection; - - @Before - public void setUp() throws ParseException { - db = createDb("test-user", "test-password"); - - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); - - Document doc1 = createDocument("firstName", "fn1") - .put("lastName", "ln1") - .put("birthDay", simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) - .put("data", new byte[]{1, 2, 3}) - .put("body", "a quick brown fox jump over the lazy dog"); - Document doc2 = createDocument("firstName", "fn2") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2010-06-12T16:02:48.440Z")) - .put("data", new byte[]{3, 4, 3}) - .put("body", "hello world from nitrite"); - Document doc3 = createDocument("firstName", "fn3") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2014-04-17T16:02:48.440Z")) - .put("data", new byte[]{9, 4, 8}) - .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + - "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); - - collection = db.getCollection("test"); - collection.remove(ALL); - - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.Unique)); - collection.insert(doc1, doc2, doc3); - } - - @After - public void tearDown() { - if (collection.isOpen()) { - collection.remove(ALL); - collection.close(); - } - if (db != null && !db.isClosed()) { - try { - db.close(); - } catch (NitriteIOException ignore) { - } - } - } - - @Test - public void testListCollectionNames() { - Set collectionNames = db.listCollectionNames(); - assertEquals(collectionNames.size(), 1); - } - - @Test - public void testListRepositories() { - db.getRepository(getClass()); - Set repositories = db.listRepositories(); - assertEquals(repositories.size(), 1); - } - - @Test - public void testHasCollection() { - assertTrue(db.hasCollection("test")); - assertFalse(db.hasCollection("lucene" + INTERNAL_NAME_SEPARATOR + "test")); - } - - @Test - public void testHasRepository() { - db.getRepository(getClass()); - assertTrue(db.hasRepository(getClass())); - assertFalse(db.hasRepository(String.class)); - } - - @Test - public void testClose() { - NitriteCollection testCollection = db.getCollection("test"); - testCollection.insert(createDocument("a", "b")); - db.close(); - - assertFalse(testCollection.isOpen()); - } - - @Test - public void testGetCollection() { - NitriteCollection collection = db.getCollection("test-collection"); - assertNotNull(collection); - assertEquals(collection.getName(), "test-collection"); - } - - @Test - public void testGetRepository() { - ObjectRepository repository = db.getRepository(NitriteTest.class); - assertNotNull(repository); - assertEquals(repository.getType(), NitriteTest.class); - } - - @Test - public void testGetRepositoryWithKey() { - ObjectRepository repository = db.getRepository(NitriteTest.class, "key"); - assertNotNull(repository); - assertEquals(repository.getType(), NitriteTest.class); - assertFalse(db.hasRepository(NitriteTest.class)); - assertTrue(db.hasRepository(NitriteTest.class, "key")); - } - - @Test - public void testMultipleGetCollection() { - NitriteCollection collection = db.getCollection("test-collection"); - assertNotNull(collection); - assertEquals(collection.getName(), "test-collection"); - - NitriteCollection collection2 = db.getCollection("test-collection"); - assertNotNull(collection2); - assertEquals(collection2.getName(), "test-collection"); - } - - @Test - public void testMultipleGetRepository() { - ObjectRepository repository = db.getRepository(NitriteTest.class); - assertNotNull(repository); - assertEquals(repository.getType(), NitriteTest.class); - - ObjectRepository repository2 = db.getRepository(NitriteTest.class); - assertNotNull(repository2); - assertEquals(repository2.getType(), NitriteTest.class); - } - - @Test(expected = ValidationException.class) - public void testGetRepositoryInvalid() { - db.getRepository(null); - } - - @Test(expected = NitriteIOException.class) - public void testGetCollectionNullStore() { - db = Nitrite.builder().openOrCreate(); - db.close(); - db.getCollection("test"); - } - - @Test(expected = NitriteIOException.class) - public void testGetRepositoryNullStore() { - db = Nitrite.builder().openOrCreate(); - db.close(); - db.getRepository(NitriteTest.class); - } - - @Test(expected = NitriteIOException.class) - public void testGetKeyedRepositoryNullStore() { - db = Nitrite.builder().openOrCreate(); - db.close(); - db.getRepository(NitriteTest.class, "key"); - } - - @Test(expected = NitriteIOException.class) - public void testCommitNullStore() { - db = Nitrite.builder().openOrCreate(); - db.close(); - db.commit(); - } - - @Test(expected = ValidationException.class) - public void testGetCollectionInvalidName() { - db.getCollection(META_MAP_NAME); - } - - @Test - public void testIssue185() throws InterruptedException { - final ObjectRepository repository = db.getRepository(Receipt.class); - final Receipt receipt = new Receipt(); - receipt.clientRef = "111-11111"; - receipt.status = Receipt.Status.PREPARING; - CountDownLatch latch = new CountDownLatch(1); - - new Thread(() -> { - for (int i = 0; i < 1000; ++i) { - try { - repository.update(receipt, true); - try { - Thread.sleep(5); - } catch (InterruptedException ignored) { - } - repository.remove(receipt); - try { - Thread.sleep(5); - } catch (InterruptedException ignored) { - } - } catch (Throwable t) { - t.printStackTrace(); - } - } - latch.countDown(); - }).start(); - - for (int i = 0; i < 1000; ++i) { - repository.find(where("status").eq(Receipt.Status.COMPLETED).not()) - .sort("createdTimestamp", SortOrder.Descending).toList(); - try { - Thread.sleep(5); - } catch (InterruptedException ignored) { - } - } - latch.await(); - } - - @Test - public void testIssue193() throws InterruptedException { - final ObjectRepository repository = db.getRepository(Receipt.class); - final PodamFactory factory = new PodamFactoryImpl(); - final String[] refs = new String[]{"1", "2", "3", "4", "5"}; - final Random random = new Random(); - ExecutorService pool = ThreadPoolManager.workerPool(); - - final CountDownLatch latch = new CountDownLatch(10000); - for (int i = 0; i < 10000; i++) { - pool.submit(() -> { - int refIndex = random.nextInt(5); - Receipt receipt = factory.manufacturePojoWithFullData(Receipt.class); - receipt.setClientRef(refs[refIndex]); - repository.update(receipt, true); - latch.countDown(); - }); - } - - latch.await(); - assertTrue(repository.find().size() <= 5); - pool.shutdown(); - } - - @Test - public void testIssue212() { - NitriteCollection collection = db.getCollection("testIssue212"); - Document doc1 = createDocument("key", "key").put("second_key", "second_key").put("third_key", "third_key"); - Document doc2 = createDocument("key", "key").put("second_key", "second_key").put("fourth_key", "fourth_key"); - Document doc = createDocument("fifth_key", "fifth_key"); - - if (!collection.hasIndex("key")) { - collection.createIndex("key", IndexOptions.indexOptions(IndexType.NonUnique)); - } - if (!collection.hasIndex("second_key")) { - collection.createIndex("second_key", IndexOptions.indexOptions(IndexType.NonUnique)); - } - - collection.insert(doc1, doc2); - collection.update(where("key").eq("key").and(where("second_key").eq("second_key")), - doc, UpdateOptions.updateOptions(true)); - - for (Document document : collection.find()) { - System.out.println(document); - } - } - - @Test - public void testIssue245() throws InterruptedException { - class ThreadRunner implements Runnable { - @Override - public void run() { - try { - long id = Thread.currentThread().getId(); - NitriteCollection collection = db.getCollection("testIssue245"); - - for (int i = 0; i < 5; i++) { - - System.out.println("Thread ID = " + id + " Inserting doc " + i); - Document doc = Document.createDocument(UUID.randomUUID().toString(), UUID.randomUUID().toString()); - - WriteResult result = collection.insert(doc);//db.commit(); - System.out.println("Result of insert = " + result.getAffectedCount()); - System.out.println("Thread id = " + id + " --> count = " + collection.size()); - - Thread.sleep(10); - - }//for closing - - collection.close(); - - } catch (Exception e) { - e.printStackTrace(); - } - } - }; - - Thread t0 = new Thread(new ThreadRunner()); - Thread t1 = new Thread(new ThreadRunner()); - Thread t2 = new Thread(new ThreadRunner()); - - t0.start(); - t1.start(); - t2.start(); - - Thread.sleep(10 * 1000); - - t0.join(); - t1.join(); - t2.join(); - - NitriteCollection collection = db.getCollection("testIssue245"); - System.out.println("No of Documents = " + collection.size()); - collection.close(); - db.close(); - } - - @Data - @AllArgsConstructor - @NoArgsConstructor - public static class CompatChild implements Mappable { - private Long childId; - private String lastName; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("childId", childId) - .put("lastName", lastName); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - childId = document.get("childId", Long.class); - lastName = document.get("lastName", String.class); - } - } - - @Data - @NoArgsConstructor - @AllArgsConstructor - @Indices({ - @Index(value = "synced", type = IndexType.NonUnique) - }) - public static class Receipt implements Mappable { - private Status status; - @Id - private String clientRef; - private Boolean synced; - private Long createdTimestamp = System.currentTimeMillis(); - - @Override - public Document write(NitriteMapper mapper) { - return createDocument("status", status) - .put("clientRef", clientRef) - .put("synced", synced) - .put("createdTimestamp", createdTimestamp); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - if (document != null) { - Object status = document.get("status"); - if (status instanceof Status) { - this.status = (Status) status; - } else { - this.status = Status.valueOf(status.toString()); - } - this.clientRef = document.get("clientRef", String.class); - this.synced = document.get("synced", Boolean.class); - this.createdTimestamp = document.get("createdTimestamp", Long.class); - } - } - - public enum Status { - COMPLETED, - PREPARING, - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/Retry.java b/nitrite/src/test/java/org/dizitart/no2/Retry.java deleted file mode 100644 index b9706d1a0..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/Retry.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.dizitart.no2; - -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; - -/** - * @author Anindya Chatterjee - */ -public class Retry implements TestRule { - private final int retryCount; - - public Retry(int retryCount) { - this.retryCount = retryCount; - } - - public Statement apply(Statement base, Description description) { - return statement(base, description); - } - - private Statement statement(final Statement base, final Description description) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - Throwable caughtThrowable = null; - - // implement retry logic here - for (int i = 0; i < retryCount; i++) { - try { - base.evaluate(); - return; - } catch (Throwable t) { - caughtThrowable = t; - System.err.println(description.getDisplayName() + ": run " + (i + 1) + " failed"); - } - } - System.err.println(description.getDisplayName() + ": giving up after " + retryCount + " failures"); - throw caughtThrowable; - } - }; - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/SerializabilityTest.java b/nitrite/src/test/java/org/dizitart/no2/SerializabilityTest.java deleted file mode 100644 index 5aad73914..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/SerializabilityTest.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.exceptions.ValidationException; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.Serializable; - -import static org.dizitart.no2.TestUtil.createDb; - -/** - * @author Anindya Chatterjee - */ -public class SerializabilityTest { - private NitriteCollection collection; - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - db = createDb(); - collection = db.getCollection("test"); - } - - @After - public void tearDown() { - if (db != null && !db.isClosed()) { - db.close(); - } - } - - @Test(expected = ValidationException.class) - public void testSerializabilityValidation() { - for (int i = 0; i < 5; i++) { - Document doc = Document.createDocument(); - doc.put("key", i); - doc.put("data", new NotSerializableClass(Integer.toString(i))); - collection.insert(doc); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("Write " + i + " completed"); - } - } - - @Test - public void testSerializablity() { - for (int i = 0; i < 5; i++) { - Document doc = Document.createDocument(); - doc.put("key", i); - doc.put("data", new SerializableClass(Integer.toString(i))); - collection.insert(doc); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("Write " + i + " completed"); - } - } - - @Data - public static class NotSerializableClass { - private String myId; - - public NotSerializableClass(String myId) { - this.myId = myId; - } - } - - @Data - public static class SerializableClass implements Serializable { - private String myId; - - public SerializableClass(String myId) { - this.myId = myId; - } - } -} - - diff --git a/nitrite/src/test/java/org/dizitart/no2/StressTest.java b/nitrite/src/test/java/org/dizitart/no2/StressTest.java deleted file mode 100644 index c8e1b5d1f..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/StressTest.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import uk.co.jemos.podam.api.PodamFactory; -import uk.co.jemos.podam.api.PodamFactoryImpl; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import java.util.concurrent.atomic.AtomicLong; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee - */ -public class StressTest { - private Nitrite db; - private NitriteCollection collection; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void before() { - db = Nitrite.builder() - .fieldSeparator(".") - .openOrCreate(); - - collection = db.getCollection("test"); - } - - @Test - public void testIssue41() { - collection.createIndex("number", IndexOptions.indexOptions(IndexType.NonUnique)); - collection.createIndex("name", IndexOptions.indexOptions(IndexType.NonUnique)); - collection.createIndex("counter", IndexOptions.indexOptions(IndexType.Unique)); - - Random random = new Random(); - AtomicLong counter = new AtomicLong(System.currentTimeMillis()); - PodamFactory factory = new PodamFactoryImpl(); - - long start = System.currentTimeMillis(); - for (int i = 0; i < 100000; i++) { - Document doc = Document.createDocument(); - doc.put("number", random.nextDouble()); - doc.put("name", factory.manufacturePojo(String.class)); - doc.put("counter", counter.getAndIncrement()); - collection.insert(doc); - if (i % 10000 == 0) { - System.out.println(i + " entries written"); - } - } - System.out.println("Records inserted in " + ((System.currentTimeMillis() - start) / (1000 * 60)) + " minutes"); - - if (db.hasUnsavedChanges()) { - db.commit(); - } - - start = System.currentTimeMillis(); - DocumentCursor cursor = collection.find(); - System.out.println("Size ->" + cursor.size()); - System.out.println("Records size calculated in " + ((System.currentTimeMillis() - start) / (1000)) + " seconds"); - - int i = 0; - start = System.currentTimeMillis(); - for (Document element : cursor) { - assertNotNull(element); - i++; - if (i % 10000 == 0) { - System.out.println(i + " entries processed"); - } - } - System.out.println("Iteration completed in " + ((System.currentTimeMillis() - start) / (1000)) + " seconds"); - } - - @After - public void clear() { - if (db != null && !db.isClosed()) { - long start = System.currentTimeMillis(); - db.close(); - System.out.println("Time to compact and close - " + (System.currentTimeMillis() - start) / 1000 + " seconds"); - } - } - - @Test - public void testRepoPerformanceWithIndex() { - // warm-up - List items = getItems(PerfTestIndexed.class); - ObjectRepository repo = db.getRepository(PerfTestIndexed.class); - for (PerfTestIndexed item : items) { - assertNotNull(item); - repo.insert(item); - } - repo.remove(Filter.ALL); - repo.drop(); - - // actual calculation - repo = db.getRepository(PerfTestIndexed.class); - long start = System.currentTimeMillis(); - for (PerfTestIndexed item : items) { - repo.insert(item); - } - long diff = System.currentTimeMillis() - start; - System.out.println("Time take to insert 10000 indexed items - " + diff + "ms"); - - start = System.currentTimeMillis(); - repo.remove(Filter.ALL); - diff = System.currentTimeMillis() - start; - System.out.println("Time take to remove 10000 indexed items - " + diff + "ms"); - } - - @Test - public void testRepoPerformanceWithoutIndex() { - // warm-up - List items = getItems(PerfTest.class); - ObjectRepository repo = db.getRepository(PerfTest.class); - for (PerfTest item : items) { - assertNotNull(item); - repo.insert(item); - } - repo.remove(Filter.ALL); - repo.drop(); - - // actual calculation - repo = db.getRepository(PerfTest.class); - long start = System.currentTimeMillis(); - for (PerfTest item : items) { - repo.insert(item); - } - long diff = System.currentTimeMillis() - start; - System.out.println("Time take to insert 10000 non-indexed items - " + diff + "ms"); - - start = System.currentTimeMillis(); - repo.remove(Filter.ALL); - diff = System.currentTimeMillis() - start; - System.out.println("Time take to remove 10000 non-indexed items - " + diff + "ms"); - } - - private List getItems(Class type) { - PodamFactory generator = new PodamFactoryImpl(); - List items = new ArrayList<>(); - for (int i = 0; i < 10000; i++) { - items.add(generator.manufacturePojoWithFullData(type)); - } - assertEquals(items.size(), 10000); - return items; - } - - @Data - public static class PerfTest implements Mappable { - private String firstName; - private String lastName; - private Integer age; - private String text; - - @Override - public Document write(NitriteMapper mapper) { - Document document = Document.createDocument(); - document.put("firstName", firstName); - document.put("lastName", lastName); - document.put("age", age); - document.put("text", text); - return document; - } - - @Override - public void read(NitriteMapper mapper, Document document) { - this.firstName = (String) document.get("firstName"); - this.lastName = (String) document.get("lastName"); - this.age = (Integer) document.get("age"); - this.text = (String) document.get("text"); - } - } - - @Indices({ - @Index(value = "firstName", type = IndexType.NonUnique), - @Index(value = "age", type = IndexType.NonUnique), - @Index(value = "text", type = IndexType.Fulltext), - }) - private static class PerfTestIndexed extends PerfTest { - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/TestUtil.java b/nitrite/src/test/java/org/dizitart/no2/TestUtil.java deleted file mode 100644 index b71985ec5..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/TestUtil.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2019-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.extern.slf4j.Slf4j; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.exceptions.ObjectMappingException; - -import java.io.IOException; -import java.util.*; - -/** - * @author Anindya Chatterjee - */ -@Slf4j -public class TestUtil { - - /** - * Determines whether the supplied `iterable` is sorted. - * - * @param the type parameter - * @param iterable the iterable - * @param ascending a boolean value indicating whether to sort in ascending order - * @return the boolean value indicating if `iterable` is sorted or not. - */ - public static > boolean isSorted(Iterable iterable, boolean ascending) { - Iterator iterator = iterable.iterator(); - if (!iterator.hasNext()) { - return true; - } - T t = iterator.next(); - while (iterator.hasNext()) { - T t2 = iterator.next(); - if (ascending) { - if (t.compareTo(t2) > 0) { - return false; - } - } else { - if (t.compareTo(t2) < 0) { - return false; - } - } - t = t2; - } - return true; - } - - public static Nitrite createDb() { - return Nitrite.builder() - .fieldSeparator(".") - .openOrCreate(); - } - - public static Nitrite createDb(String user, String password) { - return Nitrite.builder() - .fieldSeparator(".") - .openOrCreate(user, password); - } - - public static Document parse(String json) { - try { - ObjectMapper objectMapper = createObjectMapper(); - JsonNode node = objectMapper.readValue(json, JsonNode.class); - return loadDocument(node); - } catch (IOException e) { - log.error("Error while parsing json", e); - throw new ObjectMappingException("failed to parse json " + json); - } - } - - private static Document loadDocument(JsonNode node) { - Map objectMap = new LinkedHashMap<>(); - Iterator> fields = node.fields(); - while (fields.hasNext()) { - Map.Entry entry = fields.next(); - String name = entry.getKey(); - JsonNode value = entry.getValue(); - Object object = loadObject(value); - objectMap.put(name, object); - } - - return Document.createDocument(objectMap); - } - - private static Object loadObject(JsonNode node) { - if (node == null) - return null; - try { - switch (node.getNodeType()) { - case ARRAY: - return loadArray(node); - case BINARY: - return node.binaryValue(); - case BOOLEAN: - return node.booleanValue(); - case MISSING: - case NULL: - return null; - case NUMBER: - return node.numberValue(); - case OBJECT: - case POJO: - return loadDocument(node); - case STRING: - return node.textValue(); - } - } catch (IOException e) { - return null; - } - return null; - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - private static List loadArray(JsonNode array) { - if (array.isArray()) { - List list = new ArrayList(); - Iterator iterator = array.elements(); - while (iterator.hasNext()) { - Object element = iterator.next(); - if (element instanceof JsonNode) { - list.add(loadObject((JsonNode) element)); - } else { - list.add(element); - } - } - return list; - } - return null; - } - - - private static ObjectMapper createObjectMapper() { - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.setVisibility( - objectMapper.getSerializationConfig().getDefaultVisibilityChecker() - .withFieldVisibility(JsonAutoDetect.Visibility.ANY) - .withGetterVisibility(JsonAutoDetect.Visibility.NONE) - .withIsGetterVisibility(JsonAutoDetect.Visibility.NONE)); - objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); - objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); - objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true); - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - - objectMapper.findAndRegisterModules(); - return objectMapper; - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/BaseCollectionTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/BaseCollectionTest.java deleted file mode 100644 index e6ab26352..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/BaseCollectionTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import lombok.extern.slf4j.Slf4j; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.Retry; -import org.dizitart.no2.common.WriteResult; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Collection; -import java.util.Locale; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.Filter.ALL; - -@Slf4j -@RunWith(value = Parameterized.class) -public abstract class BaseCollectionTest { - @Parameterized.Parameter - public boolean isSecured = false; - - protected Nitrite db; - protected NitriteCollection collection; - protected Document doc1, doc2, doc3; - protected SimpleDateFormat simpleDateFormat; - - @Rule - public Retry retry = new Retry(3); - - @Parameterized.Parameters(name = "Secured = {0}") - public static Collection data() { - return Arrays.asList(new Object[][]{ - {false}, - {true}, - }); - } - - @Before - public void setUp() { - try { - openDb(); - - simpleDateFormat - = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); - - doc1 = createDocument("firstName", "fn1") - .put("lastName", "ln1") - .put("birthDay", simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) - .put("data", new byte[]{1, 2, 3}) - .put("list", Arrays.asList("one", "two", "three")) - .put("body", "a quick brown fox jump over the lazy dog"); - doc2 = createDocument("firstName", "fn2") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2010-06-12T16:02:48.440Z")) - .put("data", new byte[]{3, 4, 3}) - .put("list", Arrays.asList("three", "four", "three")) - .put("body", "quick hello world from nitrite"); - doc3 = createDocument("firstName", "fn3") - .put("lastName", "ln2") - .put("birthDay", simpleDateFormat.parse("2014-04-17T16:02:48.440Z")) - .put("data", new byte[]{9, 4, 8}) - .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + - "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); - - collection = db.getCollection("test"); - collection.remove(ALL); - } catch (Throwable t) { - log.error("Error while initializing test database", t); - } - } - - @After - public void clear() { - try { - if (collection != null && !collection.isDropped()) { - collection.close(); - } - if (db != null && !db.isClosed()) db.close(); - } catch (Throwable t) { - log.error("Error while clearing test database", t); - } - } - - private void openDb() { - NitriteBuilder nitriteBuilder = Nitrite.builder() - .fieldSeparator("."); - - if (isSecured) { - db = nitriteBuilder.openOrCreate("test-user", "test-password"); - } else { - db = nitriteBuilder.openOrCreate(); - } - } - - protected WriteResult insert() { - return collection.insert(doc1, doc2, doc3); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionDeleteNegativeTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/CollectionDeleteNegativeTest.java deleted file mode 100644 index 61ac96fc5..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionDeleteNegativeTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.ValidationException; -import org.junit.Test; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionDeleteNegativeTest extends BaseCollectionTest { - @Test(expected = NitriteIOException.class) - public void testDrop() { - collection.drop(); - insert(); - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - } - - @Test(expected = FilterException.class) - public void testDeleteWithInvalidFilter() { - insert(); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - - WriteResult writeResult = collection.remove(where("lastName").gt(null)); - assertEquals(writeResult.getAffectedCount(), 0); - } - - @Test(expected = ValidationException.class) - public void testDeleteNullDocument() { - insert(); - - collection.remove((Document) null); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionDeleteTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/CollectionDeleteTest.java deleted file mode 100644 index 32a513827..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionDeleteTest.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.junit.Test; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -public class CollectionDeleteTest extends BaseCollectionTest { - - @Test - public void testDelete() { - insert(); - - WriteResult writeResult = collection.remove(where("lastName").notEq(null)); - assertEquals(writeResult.getAffectedCount(), 3); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 0); - } - - @Test - public void testDeleteWithOptions() { - insert(); - - WriteResult writeResult = collection.remove(where("lastName").notEq(null), true); - assertEquals(writeResult.getAffectedCount(), 1); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 2); - } - - @Test - public void testDeleteWithNonMatchingFilter() { - insert(); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - - WriteResult writeResult = collection.remove(where("lastName").eq("a")); - assertEquals(writeResult.getAffectedCount(), 0); - } - - @Test - public void testDeleteInEmptyCollection() { - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 0); - - WriteResult writeResult = collection.remove(where("lastName").notEq(null)); - assertEquals(writeResult.getAffectedCount(), 0); - } - - @Test - public void testClear() { - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.Unique)); - insert(); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - assertTrue(collection.hasIndex("firstName")); - - boolean uniqueError = false; - try { - collection.insert(doc1); - } catch (Exception e) { - uniqueError = true; - } finally { - assertTrue(uniqueError); - } - - collection.remove(Filter.ALL); - - cursor = collection.find(); - assertEquals(cursor.size(), 0); - assertTrue(collection.hasIndex("firstName")); - - collection.insert(doc1); - cursor = collection.find(); - assertEquals(cursor.size(), 1); - assertTrue(collection.hasIndex("firstName")); - } - - @Test - public void testRemoveAll() { - insert(); - WriteResult writeResult = collection.remove((Filter) null); - assertEquals(writeResult.getAffectedCount(), 3); - } - - @Test - public void testRemoveDocument() { - insert(); - - WriteResult writeResult = collection.remove(where("firstName").eq("fn1")); - assertEquals(writeResult.getAffectedCount(), 1); - assertEquals(collection.size(), 2); - - writeResult = collection.remove(where("firstName").eq("fn2")); - assertEquals(writeResult.getAffectedCount(), 1); - assertEquals(collection.size(), 1); - - assertEquals(collection.find(where("firstName").eq("fn1")).size(), 0); - assertEquals(collection.find(where("firstName").eq("fn2")).size(), 0); - assertEquals(collection.find(where("firstName").eq("fn3")).size(), 1); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionFactoryTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/CollectionFactoryTest.java index 47677200a..7b52816de 100644 --- a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionFactoryTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/collection/CollectionFactoryTest.java @@ -17,7 +17,7 @@ package org.dizitart.no2.collection; import org.dizitart.no2.NitriteConfig; -import org.dizitart.no2.Retry; +import org.dizitart.no2.integration.Retry; import org.dizitart.no2.common.concurrent.LockService; import org.dizitart.no2.exceptions.ValidationException; import org.junit.Rule; diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionFindByIndexNegativeTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/CollectionFindByIndexNegativeTest.java deleted file mode 100644 index feb80b76b..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionFindByIndexNegativeTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.junit.Test; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionFindByIndexNegativeTest extends BaseCollectionTest { - @Test(expected = FilterException.class) - public void testFindTextWithWildCardMultipleWord() { - insert(); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - - DocumentCursor cursor = collection.find(where("body").text("*ipsum dolor*")); - assertEquals(cursor.size(), 1); - } - - @Test(expected = FilterException.class) - public void testFindTextWithOnlyWildCard() { - insert(); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - - DocumentCursor cursor = collection.find(where("body").text("*")); - assertEquals(cursor.size(), 1); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionFindByIndexTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/CollectionFindByIndexTest.java deleted file mode 100644 index 1b1859fb1..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionFindByIndexTest.java +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import com.github.javafaker.Faker; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.junit.Test; - -import java.text.ParseException; -import java.util.*; - -import static org.dizitart.no2.TestUtil.isSorted; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionFindByIndexTest extends BaseCollectionTest { - - @Test - public void testFindByUniqueIndex() throws ParseException { - insert(); - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.Unique)); - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("firstName").eq("fn10")); - assertEquals(cursor.size(), 0); - - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.Unique)); - cursor = collection.find(where("birthDay").gt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").gte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lte( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").lt( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").gt( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").gte( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .and(where("firstName").eq("fn1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12"))); - assertEquals(cursor.size(), 3); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1")).not()); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").eq((byte) 4)); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").lt(4)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("firstName").notIn("fn1", "fn2")); - assertEquals(cursor.size(), 1); - } - - @Test - public void testFindByNonUniqueIndex() throws ParseException { - insert(); - collection.createIndex("lastName", IndexOptions.indexOptions(IndexType.NonUnique)); - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.NonUnique)); - - DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("lastName").eq("ln20")); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").gt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").gte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lte( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").lt( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").gt( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").gte( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .and(where("firstName").eq("fn1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12"))); - assertEquals(cursor.size(), 3); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1")).not()); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").eq((byte) 4)); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").lt(4)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("firstName").notIn("fn1", "fn2")); - assertEquals(cursor.size(), 1); - } - - @Test - public void testFindByFullTextIndexAfterInsert() { - insert(); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("body")); - - DocumentCursor cursor = collection.find(where("body").text("Lorem")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("body").text("nosql")); - assertEquals(cursor.size(), 0); - - collection.dropIndex("body"); - boolean filterException = false; - try { - collection.find(where("body").text("Lorem")).toList(); - } catch (FilterException fe) { - filterException = true; - } finally { - assertTrue(filterException); - } - } - - @Test - public void testFindByFullTextIndexBeforeInsert() { - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("body")); - insert(); - - DocumentCursor cursor = collection.find(where("body").text("Lorem")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("body").text("quick brown")); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("body").text("nosql")); - assertEquals(cursor.size(), 0); - - collection.dropIndex("body"); - boolean filterException = false; - try { - collection.find(where("body").text("Lorem")).toList(); - } catch (FilterException fe) { - filterException = true; - } finally { - assertTrue(filterException); - } - } - - @Test - public void testFindByIndexSortAscending() { - insert(); - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.Unique)); - - DocumentCursor cursor = collection.find().sort("birthDay", SortOrder.Ascending); - assertEquals(cursor.size(), 3); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, true)); - } - - @Test - public void testFindByIndexSortDescending() { - insert(); - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.Unique)); - - DocumentCursor cursor = collection.find().sort("birthDay", SortOrder.Descending); - assertEquals(cursor.size(), 3); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, false)); - } - - @Test - public void testFindByIndexLimitAndSort() { - insert(); - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.Unique)); - - DocumentCursor cursor = collection.find(). - sort("birthDay", SortOrder.Descending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, false)); - - cursor = collection.find(). - sort("birthDay", SortOrder.Ascending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, true)); - - cursor = collection.find(). - sort("firstName", SortOrder.Ascending).skipLimit(0, 30); - assertEquals(cursor.size(), 3); - List nameList = new ArrayList<>(); - for (Document document : cursor) { - nameList.add(document.get("firstName", String.class)); - } - assertTrue(isSorted(nameList, true)); - } - - @Test - public void testFindAfterDroppedIndex() { - insert(); - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.Unique)); - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - - collection.dropIndex("firstName"); - cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - } - - @Test - public void testFindTextWithWildCard() { - insert(); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - - DocumentCursor cursor = collection.find(where("body").text("Lo")); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("body").text("Lo*")); - assertEquals(cursor.size(), 1); // Lorem - - cursor = collection.find(where("body").text("*rem")); - assertEquals(cursor.size(), 1); // lorem - - cursor = collection.find(where("body").text("*or*")); - assertEquals(cursor.size(), 2); - } - - @Test - public void testFindTextWithEmptyString() { - insert(); - collection.createIndex("body", IndexOptions.indexOptions(IndexType.Fulltext)); - - DocumentCursor cursor = collection.find(where("body").text("")); - assertEquals(cursor.size(), 0); - } - - @Test - public void testFindWithOrIndexed() { - NitriteCollection collection = db.getCollection("testFindWithOrIndexed"); - Document doc1 = Document.createDocument("firstName", "John").put("lastName", "Doe"); - Document doc2 = Document.createDocument("firstName", "Jane").put("lastName", "Doe"); - Document doc3 = Document.createDocument("firstName", "Jonas").put("lastName", "Doe"); - Document doc4 = Document.createDocument("firstName", "Johan").put("lastName", "Day"); - - collection.createIndex("firstName", IndexOptions.indexOptions(IndexType.Unique)); - collection.createIndex("lastName", IndexOptions.indexOptions(IndexType.NonUnique)); - - collection.insert(doc1, doc2, doc3, doc4); - - DocumentCursor cursor = collection.find(where("firstName").eq("John").or(where("lastName").eq("Day"))); - assertEquals(cursor.size(), 2); - - List list = cursor.toList(); - assertEquals(list.size(), 2); - } - - @Test - public void testIssue45() { - NitriteCollection collection = db.getCollection("testIssue45"); - Faker faker = new Faker(); - String text1 = faker.lorem().paragraph() + " quick brown"; - String text2 = faker.lorem().paragraph() + " fox jump"; - String text3 = faker.lorem().paragraph() + " over lazy"; - String text4 = faker.lorem().paragraph() + " dog"; - - List list1 = Arrays.asList(text1, text2); - List list2 = Arrays.asList(text1, text2, text3); - List list3 = Arrays.asList(text2, text3); - List list4 = Arrays.asList(text1, text2, text3, text4); - - Document doc1 = Document.createDocument("firstName", "John").put("notes", list1); - Document doc2 = Document.createDocument("firstName", "Jane").put("notes", list2); - Document doc3 = Document.createDocument("firstName", "Jonas").put("notes", list3); - Document doc4 = Document.createDocument("firstName", "Johan").put("notes", list4); - - collection.createIndex("notes", IndexOptions.indexOptions(IndexType.Fulltext)); - collection.insert(doc1, doc2, doc3, doc4); - - DocumentCursor cursor = collection.find(where("notes").text("fox")); - assertEquals(cursor.size(), 4); - - cursor = collection.find(where("notes").text("dog")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("notes").text("lazy")); - assertEquals(cursor.size(), 3); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionFindNegativeTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/CollectionFindNegativeTest.java deleted file mode 100644 index cf85610fe..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionFindNegativeTest.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.exceptions.ValidationException; -import org.junit.Test; - -import java.util.Date; -import java.util.List; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionFindNegativeTest extends BaseCollectionTest { - @Test(expected = ValidationException.class) - public void testFindFilterInvalidIndex() { - insert(); - collection.find(where("data.9").eq(4)).toList(); - } - - @Test(expected = ValidationException.class) - public void testFindOptionsNegativeOffset() { - insert(); - collection.find().skipLimit(-1, 1); - } - - @Test(expected = ValidationException.class) - public void testFindOptionsNegativeSize() { - insert(); - collection.find().skipLimit(0, -1); - } - - public void testFindOptionsInvalidOffset() { - insert(); - assertEquals(collection.find().skipLimit(10, 1).size(), 0); - } - - @Test(expected = ValidationException.class) - public void testFindInvalidSort() { - insert(); - collection.find().sort("data", SortOrder.Descending).toList(); - } - - @Test(expected = FilterException.class) - public void testFindTextFilterNonIndexed() { - insert(); - collection.find(where("body").text("Lorem")).toList(); - } - - @Test(expected = FilterException.class) - public void testFindWithRegexInvalidValue() { - insert(); - DocumentCursor cursor = collection.find(where("birthDay").regex("hello")); - assertEquals(cursor.size(), 1); - } - - @Test(expected = ValidationException.class) - public void testInvalidProjection() { - insert(); - DocumentCursor cursor = collection.find(where("birthDay").lte(new Date())). - sort("firstName", SortOrder.Ascending).skipLimit(0, 3); - - Document projection = createDocument("firstName", null) - .put("lastName", "ln2"); - - cursor.project(projection); - } - - @Test(expected = UnsupportedOperationException.class) - public void testToListAdd() { - insert(); - DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); - List documents = cursor.toList(); - documents.add(createDocument()); - } - - @Test(expected = UnsupportedOperationException.class) - public void testToListRemove() { - insert(); - DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); - List documents = cursor.toList(); - documents.clear(); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionFindTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/CollectionFindTest.java deleted file mode 100644 index 0230aa359..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionFindTest.java +++ /dev/null @@ -1,856 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.common.NullOrder; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.exceptions.IndexingException; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.joda.time.DateTime; -import org.junit.Test; - -import java.text.Collator; -import java.text.ParseException; -import java.util.*; -import java.util.stream.Collectors; - -import static org.dizitart.no2.TestUtil.isSorted; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.common.Constants.*; -import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.$; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.*; - -public class CollectionFindTest extends BaseCollectionTest { - - private static Document trimMeta(Document document) { - document.remove(DOC_ID); - document.remove(DOC_REVISION); - document.remove(DOC_MODIFIED); - document.remove(DOC_SOURCE); - return document; - } - - @Test - public void testFindAll() { - insert(); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - } - - @Test - public void testFindWithFilter() throws ParseException { - insert(); - - DocumentCursor cursor = collection.find(where("birthDay").gt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").gte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lt( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("birthDay").lte( - simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("birthDay").lte( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").lt( - new Date())); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("birthDay").gt( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("birthDay").gte( - new Date())); - assertEquals(cursor.size(), 0); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .and(where("firstName").eq("fn1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12"))); - assertEquals(cursor.size(), 3); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1"))); - assertEquals(cursor.size(), 1); - - cursor = collection.find( - where("birthDay").lte(new Date()) - .or(where("firstName").eq("fn12")) - .and(where("lastName").eq("ln1")).not()); - assertEquals(cursor.size(), 2); - - - cursor = collection.find(where("data.1").eq((byte) 4)); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("data.1").lt(4)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("firstName").notIn("fn1", "fn2")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(ALL.not()); - assertEquals(cursor.size(), 0); - } - - @Test - public void testFindWithSkipLimit() { - insert(); - - DocumentCursor cursor = collection.find().skipLimit(0, 1); - assertEquals(cursor.size(), 1); - - cursor = collection.find().skipLimit(1, 3); - assertEquals(cursor.size(), 2); - - cursor = collection.find().skipLimit(0, 30); - assertEquals(cursor.size(), 3); - - cursor = collection.find().skipLimit(2, 3); - assertEquals(cursor.size(), 1); - } - - @Test - public void testFindWithSkip() { - insert(); - - DocumentCursor cursor = collection.find().skip(0); - assertEquals(cursor.size(), 3); - - cursor = collection.find().skip(1); - assertEquals(cursor.size(), 2); - - cursor = collection.find().skip(30); - assertEquals(cursor.size(), 0); - - cursor = collection.find().skip(2); - assertEquals(cursor.size(), 1); - - boolean invalid = false; - try { - cursor = collection.find().skip(-1); - assertEquals(cursor.size(), 1); - } catch (ValidationException e) { - invalid = true; - } - assertTrue(invalid); - } - - @Test - public void testFindWithLimit() { - insert(); - - DocumentCursor cursor = collection.find().limit(0); - assertEquals(cursor.size(), 0); - - cursor = collection.find().limit(1); - assertEquals(cursor.size(), 1); - - boolean invalid = false; - try { - cursor = collection.find().limit(-1); - assertEquals(cursor.size(), 1); - } catch (ValidationException e) { - invalid = true; - } - assertTrue(invalid); - - cursor = collection.find().limit(30); - assertEquals(cursor.size(), 3); - } - - @Test - public void testFindSortAscending() { - insert(); - - DocumentCursor cursor = collection.find().sort("birthDay", SortOrder.Ascending); - assertEquals(cursor.size(), 3); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, true)); - } - - @Test - public void testFindSortDescending() { - insert(); - - DocumentCursor cursor = collection.find().sort("birthDay", SortOrder.Descending); - assertEquals(cursor.size(), 3); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, false)); - } - - @Test - public void testFindLimitAndSort() { - insert(); - - DocumentCursor cursor = collection.find(). - sort("birthDay", SortOrder.Descending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - List dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, false)); - - cursor = collection.find(). - sort("birthDay", SortOrder.Ascending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - dateList = new ArrayList<>(); - for (Document document : cursor) { - dateList.add(document.get("birthDay", Date.class)); - } - assertTrue(isSorted(dateList, true)); - - cursor = collection.find(). - sort("firstName", SortOrder.Ascending).skipLimit(0, 30); - assertEquals(cursor.size(), 3); - List nameList = new ArrayList<>(); - for (Document document : cursor) { - nameList.add(document.get("firstName", String.class)); - } - assertTrue(isSorted(nameList, true)); - } - - @Test - public void testFindSortOnNonExistingField() { - insert(); - DocumentCursor cursor = collection.find().sort("my-value", SortOrder.Descending); - assertEquals(cursor.size(), 3); - } - - @Test - public void testFindInvalidField() { - insert(); - DocumentCursor cursor = collection.find(where("myField").eq("myData")); - assertEquals(cursor.size(), 0); - } - - @Test - public void testFindInvalidFieldWithInvalidAccessor() { - insert(); - DocumentCursor cursor = collection.find(where("myField.0").eq("myData")); - assertEquals(cursor.size(), 0); - } - - @Test - public void testFindLimitAndSortInvalidField() { - insert(); - DocumentCursor cursor = collection.find(). - sort("birthDay2", SortOrder.Descending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - } - - @Test - public void testGetById() { - collection.insert(doc1); - NitriteId id = NitriteId.createId("1"); - Document document = collection.getById(id); - assertNull(document); - - document = collection.find().firstOrNull(); - - assertEquals(document.get(DOC_ID), document.getId().getIdValue()); - assertEquals(document.get("firstName"), "fn1"); - assertEquals(document.get("lastName"), "ln1"); - assertArrayEquals((byte[]) document.get("data"), new byte[]{1, 2, 3}); - assertEquals(document.get("body"), "a quick brown fox jump over the lazy dog"); - } - - @Test - public void testFindWithFilterAndOption() { - insert(); - DocumentCursor cursor = collection.find(where("birthDay").lte(new Date())). - sort("firstName", SortOrder.Ascending).skipLimit(1, 2); - assertEquals(cursor.size(), 2); - } - - @Test - public void testFindTextWithRegex() { - insert(); - DocumentCursor cursor = collection.find(where("body").regex("hello")); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("body").regex("test")); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("body").regex("^hello$")); - assertEquals(cursor.size(), 0); - - cursor = collection.find(where("body").regex(".*")); - assertEquals(cursor.size(), 3); - } - - @Test - public void testProject() { - insert(); - DocumentCursor cursor = collection.find(where("birthDay").lte(new Date())). - sort("firstName", SortOrder.Ascending).skipLimit(0, 3); - int iteration = 0; - for (Document document : cursor) { - switch (iteration) { - case 0: - assertTrue(isSimilar(document, doc1, "firstName", "lastName", "birthDay", "data", "list", "body")); - break; - case 1: - assertTrue(isSimilar(document, doc2, "firstName", "lastName", "birthDay", "data", "list", "body")); - break; - case 2: - assertTrue(isSimilar(document, doc3, "firstName", "lastName", "birthDay", "data", "list", "body")); - break; - } - iteration++; - } - assertEquals(iteration, 3); - } - - @Test - public void testProjectWithCustomDocument() { - insert(); - DocumentCursor cursor = collection.find(where("birthDay").lte(new Date())). - sort("firstName", SortOrder.Ascending).skipLimit(0, 3); - - Document projection = createDocument("firstName", null) - .put("lastName", null); - - Iterable documents = cursor.project(projection); - int iteration = 0; - for (Document document : documents) { - assertTrue(document.containsKey("firstName")); - assertTrue(document.containsKey("lastName")); - - assertFalse(document.containsKey("_id")); - assertFalse(document.containsKey("birthDay")); - assertFalse(document.containsKey("data")); - assertFalse(document.containsKey("body")); - - switch (iteration) { - case 0: - assertEquals(document.get("firstName"), "fn1"); - assertEquals(document.get("lastName"), "ln1"); - break; - case 1: - assertEquals(document.get("firstName"), "fn2"); - assertEquals(document.get("lastName"), "ln2"); - break; - case 2: - assertEquals(document.get("firstName"), "fn3"); - assertEquals(document.get("lastName"), "ln2"); - break; - } - iteration++; - } - assertEquals(iteration, 3); - } - - @Test - public void testFindWithArrayEqual() { - insert(); - DocumentCursor ids = collection.find(where("data").eq(new byte[]{3, 4, 3})); - assertNotNull(ids); - assertEquals(ids.size(), 1); - } - - @Test - public void testFindWithArrayEqualFailForWrongCardinality() { - insert(); - DocumentCursor ids = collection.find(where("data").eq(new byte[]{4, 3, 3})); - assertNotNull(ids); - assertEquals(ids.size(), 0); - } - - @Test - public void testFindWithIterableEqual() { - insert(); - DocumentCursor ids = collection.find(where("list").eq( - new ArrayList() {{ - add("three"); - add("four"); - add("three"); - }})); - assertNotNull(ids); - assertEquals(ids.size(), 1); - } - - @Test - public void testFindWithIterableEqualFailForWrongCardinality() { - insert(); - DocumentCursor ids = collection.find(where("list").eq( - new ArrayList() {{ - add("four"); - add("three"); - add("three"); - }})); - assertNotNull(ids); - assertEquals(ids.size(), 0); - } - - @Test - public void testFindInArray() { - insert(); - DocumentCursor ids = collection.find(where("data").elemMatch($.gte(2).and($.lt(5)))); - assertNotNull(ids); - assertEquals(ids.size(), 3); - - ids = collection.find(where("data").elemMatch($.gt(2).or($.lte(5)))); - assertNotNull(ids); - assertEquals(ids.size(), 3); - - ids = collection.find(where("data").elemMatch($.gt(1).and($.lt(4)))); - assertNotNull(ids); - assertEquals(ids.size(), 2); - } - - @Test - public void testFindInList() { - insert(); - DocumentCursor ids = collection.find(where("list").elemMatch($.regex("three"))); - assertNotNull(ids); - assertEquals(ids.size(), 2); - - ids = collection.find(where("list").elemMatch($.regex("hello"))); - assertNotNull(ids); - assertEquals(ids.size(), 0); - - ids = collection.find(where("list").elemMatch($.regex("hello").not())); - assertNotNull(ids); - assertEquals(ids.size(), 2); - } - - @Test - public void testElemMatchFilter() { - Document doc1 = createDocument("productScores", new Document[]{ - createDocument("product", "abc").put("score", 10), - createDocument("product", "xyz").put("score", 5) - }).put("strArray", new String[]{"a", "b"}); - - Document doc2 = createDocument("productScores", new Document[]{ - createDocument("product", "abc").put("score", 8), - createDocument("product", "xyz").put("score", 7) - }).put("strArray", new String[]{"d", "e"}); - - Document doc3 = createDocument("productScores", new Document[]{ - createDocument("product", "abc").put("score", 7), - createDocument("product", "xyz").put("score", 8) - }).put("strArray", new String[]{"a", "f"}); - - NitriteCollection prodCollection = db.getCollection("prodScore"); - prodCollection.insert(doc1, doc2, doc3); - - List documentList = prodCollection.find(where("productScores") - .elemMatch(where("product").eq("xyz").and(where("score").gte(8)))).toList(); - - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").lte(8).not())).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("product").eq("xyz").or(where("score").gte(8)))).toList(); - assertEquals(documentList.size(), 3); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("product").eq("xyz"))).toList(); - assertEquals(documentList.size(), 3); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").gte(10))).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").gt(8))).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").lt(7))).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").lte(7))).toList(); - assertEquals(documentList.size(), 3); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").in(7, 8))).toList(); - assertEquals(documentList.size(), 2); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("score").notIn(7, 8))).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("productScores") - .elemMatch(where("product").regex("xyz"))).toList(); - assertEquals(documentList.size(), 3); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.eq("a"))).toList(); - assertEquals(documentList.size(), 2); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.eq("a").or($.eq("f").or($.eq("b"))).not())).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.gt("e"))).toList(); - assertEquals(documentList.size(), 1); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.gte("e"))).toList(); - assertEquals(documentList.size(), 2); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.lte("b"))).toList(); - assertEquals(documentList.size(), 2); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.lt("a"))).toList(); - assertEquals(documentList.size(), 0); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.in("a", "f"))).toList(); - assertEquals(documentList.size(), 2); - - documentList = prodCollection.find(where("strArray") - .elemMatch($.regex("a"))).toList(); - assertEquals(documentList.size(), 2); - - } - - @Test - public void testNotEqualFilter() { - Document document = createDocument("abc", "123"); - document.put("xyz", null); - - collection.insert(document); - DocumentCursor cursor = collection.find(where("abc").eq("123")); - assertEquals(cursor.size(), 1); - assertEquals(cursor.toList().size(), 1); - - cursor = collection.find(where("xyz").eq(null)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("abc").notEq(null)); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("abc").notEq(null).and(where("xyz").eq(null))); - assertEquals(cursor.size(), 1); - - cursor = collection.find(where("abc").eq(null).and(where("xyz").notEq(null))); - assertEquals(cursor.size(), 0); - - collection.remove(ALL); - - document = createDocument("field", "two"); - document.put(DOC_REVISION, 1482225343161L); - - collection.insert(document); - Document projection = collection.find( - where(DOC_REVISION).gte(1482225343160L) - .and(where(DOC_REVISION).lte(1482225343162L) - .and(where(DOC_REVISION).notEq(null)))) - .firstOrNull(); - - assertNull(projection); - } - - @Test - public void testFilterAll() { - DocumentCursor cursor = collection.find(ALL); - assertNotNull(cursor); - assertEquals(cursor.size(), 0); - - insert(); - cursor = collection.find(ALL); - assertNotNull(cursor); - assertEquals(cursor.size(), 3); - } - - @Test - public void testIssue72() { - NitriteCollection coll = db.getCollection("test"); - coll.createIndex("id", IndexOptions.indexOptions(IndexType.Unique)); - coll.createIndex("group", IndexOptions.indexOptions(IndexType.NonUnique)); - - coll.remove(ALL); - - Document doc = createDocument().put("id", "test-1").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - doc = createDocument().put("id", "test-2").put("group", "groupA").put("startTime", DateTime.now()); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - DocumentCursor cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending); - assertEquals(2, cursor.size()); - assertNull(cursor.toList().get(1).get("startTime")); - assertNotNull(cursor.toList().get(0).get("startTime")); - - cursor = coll.find(where("group").eq("groupA")).sort("startTime", SortOrder.Ascending); - assertEquals(2, cursor.size()); - assertNull(cursor.toList().get(0).get("startTime")); - assertNotNull(cursor.toList().get(1).get("startTime")); - } - - @Test - public void testIssue93() { - NitriteCollection coll = db.getCollection("orderByOnNullableColumn2"); - - coll.remove(ALL); - - Document doc = createDocument().put("id", "test-2").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - doc = createDocument().put("id", "test-1").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - DocumentCursor cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending); - assertEquals(2, cursor.size()); - } - - @Test - public void testNullOrderWithAllNull() { - NitriteCollection coll = db.getCollection("test"); - - coll.remove(ALL); - - Document doc = createDocument().put("id", "test-2").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - doc = createDocument().put("id", "test-1").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - DocumentCursor cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending); - assertEquals(2, cursor.size()); - - DocumentCursor cursor2 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.Default); - assertEquals(2, cursor2.size()); - - assertThat(cursor.toList(), is(cursor2.toList())); - - DocumentCursor cursor3 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.First); - assertEquals(2, cursor3.size()); - - assertThat(cursor.toList(), is(cursor3.toList())); - - DocumentCursor cursor4 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.Last); - assertEquals(2, cursor4.size()); - - assertThat(cursor.toList(), is(cursor4.toList())); - - DocumentCursor cursor5 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.Last); - assertEquals(2, cursor5.size()); - - assertThat(cursor.toList(), is(cursor5.toList())); - - DocumentCursor cursor6 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.First); - assertEquals(2, cursor6.size()); - - assertThat(cursor.toList(), is(cursor6.toList())); - - DocumentCursor cursor7 = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.Default); - assertEquals(2, cursor7.size()); - - assertThat(cursor.toList(), is(cursor7.toList())); - } - - @Test - public void testNullOrder() { - NitriteCollection coll = db.getCollection("test"); - try { - coll.createIndex("startTime", IndexOptions.indexOptions(IndexType.NonUnique)); - } catch (IndexingException e) { - // ignore - } - - coll.remove(ALL); - - Document doc1 = createDocument().put("id", "test-1").put("group", "groupA"); - assertEquals(1, coll.insert(doc1).getAffectedCount()); - - Document doc2 = createDocument().put("id", "test-2").put("group", "groupA").put("startTime", DateTime.now()); - assertEquals(1, coll.insert(doc2).getAffectedCount()); - - Document doc3 = createDocument().put("id", "test-3").put("group", "groupA").put("startTime", DateTime.now().plusMinutes(1)); - assertEquals(1, coll.insert(doc3).getAffectedCount()); - - DocumentCursor cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc3, doc2, doc1), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.First); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc1, doc3, doc2), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.Default); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc3, doc2, doc1), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Descending, NullOrder.Last); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc3, doc2, doc1), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.First); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc1, doc2, doc3), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.Default); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc1, doc2, doc3), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - - cursor = coll.find(where("group").eq("groupA")) - .sort("startTime", SortOrder.Ascending, NullOrder.Last); - assertEquals(3, cursor.size()); - assertThat(Arrays.asList(doc2, doc3, doc1), - is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); - } - - @Test - public void testFindFilterInvalidAccessor() { - insert(); - DocumentCursor cursor = collection.find(where("lastName.name").eq("ln2")); - assertEquals(cursor.size(), 0); - } - - @Test - public void testIssue144() { - Document doc1 = createDocument().put("id", "test-1").put("fruit", "Apple"); - Document doc2 = createDocument().put("id", "test-2").put("fruit", "Ôrange"); - Document doc3 = createDocument().put("id", "test-3").put("fruit", "Pineapple"); - - NitriteCollection coll = db.getCollection("test"); - coll.insert(doc1, doc2, doc3); - - DocumentCursor cursor = coll.find().sort("fruit", SortOrder.Ascending, - Collator.getInstance(Locale.FRANCE)); - assertEquals(cursor.toList().get(1).get("fruit"), "Ôrange"); - } - - @Test - public void testIdSet() { - insert(); - DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); - assertEquals(cursor.size(), 2); - - cursor = collection.find(where("lastName").eq("ln1")); - assertEquals(cursor.size(), 1); - - Document byId = cursor.iterator().next(); - assertEquals(byId.get("lastName"), "ln1"); - } - - @Test - public void testCollectionField() { - Document document = createDocument("name", "John") - .put("tags", new Document[]{ - createDocument("type", "example").put("other", "value"), - createDocument("type", "another-example").put("other", "some-other-value") - }); - - NitriteCollection example = db.getCollection("example"); - example.insert(document); - - document = createDocument("name", "Jane") - .put("tags", new Document[]{ - createDocument("type", "example2").put("other", "value2"), - createDocument("type", "another-example2").put("other", "some-other-value2") - }); - example.insert(document); - - DocumentCursor cursor = example.find(where("tags").elemMatch(where("type").eq("example"))); - for (Document doc : cursor) { - assertNotNull(doc); - assertEquals(doc.get("name"), "John"); - } - } - - @Test - public void testBetweenFilter() { - Document doc1 = createDocument("age", 31).put("tag", "one"); - Document doc2 = createDocument("age", 32).put("tag", "two"); - Document doc3 = createDocument("age", 33).put("tag", "three"); - Document doc4 = createDocument("age", 34).put("tag", "four"); - Document doc5 = createDocument("age", 35).put("tag", "five"); - - NitriteCollection collection = db.getCollection("tag"); - collection.insert(doc1, doc2, doc3, doc4, doc5); - collection.createIndex("age", IndexOptions.indexOptions(IndexType.Unique)); - - DocumentCursor cursor = collection.find(where("age").between(31, 35)); - assertEquals(cursor.size(), 5); - - cursor = collection.find(where("age").between(31, 35, false)); - assertEquals(cursor.size(), 3); - - cursor = collection.find(where("age").between(31, 35, false, true)); - assertEquals(cursor.size(), 4); - - cursor = collection.find(where("age").between(31, 35, false).not()); - assertEquals(cursor.size(), 2); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionIndexNegativeTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/CollectionIndexNegativeTest.java deleted file mode 100644 index 3c0828520..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionIndexNegativeTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.exceptions.IndexingException; -import org.dizitart.no2.exceptions.UniqueConstraintException; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.junit.Test; - -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionIndexNegativeTest extends BaseCollectionTest { - - @Test(expected = UniqueConstraintException.class) - public void testCreateInvalidUniqueIndex() { - collection.createIndex("lastName", IndexOptions.indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("lastName")); - insert(); - } - - @Test(expected = UniqueConstraintException.class) - public void testCreateIndexOnArray() { - collection.createIndex("data", IndexOptions.indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("data")); - // data array field has repetition, so unique constraint exception - insert(); - } - - @Test - public void testCreateOnInvalidField() { - insert(); - collection.createIndex("my-value", IndexOptions.indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("my-value")); - } - - @Test(expected = IndexingException.class) - public void testCreateFullTextOnNonTextField() { - insert(); - collection.createIndex("birthDay", IndexOptions.indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("birthDay")); - } - - @Test(expected = IndexingException.class) - public void testDropIndexOnNonIndexedField() { - collection.dropIndex("data"); - } - - @Test(expected = IndexingException.class) - public void testRebuildIndexInvalid() { - collection.rebuildIndex("unknown", true); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionIndexTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/CollectionIndexTest.java deleted file mode 100644 index 161e52626..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionIndexTest.java +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.IndexingException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexEntry; -import org.dizitart.no2.index.IndexType; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import java.util.concurrent.Callable; - -import static org.awaitility.Awaitility.await; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionIndexTest extends BaseCollectionTest { - - @Test - public void testCreateIndex() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("firstName")); - - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - assertTrue(collection.hasIndex("lastName")); - - collection.createIndex("body", indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("body")); - - collection.createIndex("birthDay", null); - assertTrue(collection.hasIndex("birthDay")); - - insert(); - } - - @Test - public void testListIndexes() { - assertEquals(collection.listIndices().size(), 0); - - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("firstName")); - - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - assertTrue(collection.hasIndex("lastName")); - - collection.createIndex("body", indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("body")); - - assertEquals(collection.listIndices().size(), 3); - } - - @Test - public void testDropIndex() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("firstName")); - - collection.dropIndex("firstName"); - assertFalse(collection.hasIndex("firstName")); - } - - @Test - public void testDropAllIndexes() { - collection.dropAllIndices(); - - testCreateIndex(); - assertEquals(collection.listIndices().size(), 4); - - collection.dropAllIndices(); - assertEquals(collection.listIndices().size(), 0); - } - - @Test - public void testHasIndex() { - assertFalse(collection.hasIndex("lastName")); - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - assertTrue(collection.hasIndex("lastName")); - - assertFalse(collection.hasIndex("body")); - collection.createIndex("body", indexOptions(IndexType.Fulltext)); - assertTrue(collection.hasIndex("body")); - } - - @Test - public void testDeleteWithIndex() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("body", indexOptions(IndexType.Fulltext)); - - insert(); - - WriteResult result = collection.remove(where("firstName").eq("fn1")); - assertEquals(result.getAffectedCount(), 1); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 2); - - result = collection.remove(where("body").text("Lorem")); - assertEquals(result.getAffectedCount(), 1); - - cursor = collection.find(); - assertEquals(cursor.size(), 1); - } - - @Test - public void testCreateIndexAsync() { - insert(); - collection.createIndex("body", indexOptions(IndexType.Fulltext, true)); - assertTrue(collection.isIndexing("body")); - - await().until(bodyIndexingCompleted()); - } - - @Test - public void testRebuildIndex() { - collection.createIndex("body", indexOptions(IndexType.Fulltext, false)); - insert(); - Collection indices = collection.listIndices(); - for (IndexEntry idx : indices) { - collection.rebuildIndex(idx.getField(), false); - } - } - - @Test - public void testRebuildIndexAsync() { - collection.createIndex("body", indexOptions(IndexType.Fulltext, true)); - insert(); - await().until(bodyIndexingCompleted()); - - Collection indices = collection.listIndices(); - for (IndexEntry idx : indices) { - collection.rebuildIndex(idx.getField(), true); - await().until(bodyIndexingCompleted()); - } - } - - @Test - public void testRebuildIndexOnRunningIndex() { - collection.createIndex("body", indexOptions(IndexType.Fulltext, false)); - Collection indices = collection.listIndices(); - IndexEntry idx = indices.iterator().next(); - insert(); - collection.rebuildIndex(idx.getField(), true); - - boolean error = false; - try { - collection.rebuildIndex(idx.getField(), true); - } catch (IndexingException ie) { - error = true; - } finally { - assertTrue(error); - await().until(bodyIndexingCompleted()); - } - } - - private Callable bodyIndexingCompleted() { - return () -> !collection.isIndexing("body"); - } - - @Test - public void testNullValueInIndexedField() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("birthDay", indexOptions(IndexType.NonUnique)); - insert(); - - Document document = createDocument("firstName", null) - .put("lastName", "ln1") - .put("birthDay", null) - .put("data", new byte[]{1, 2, 3}) - .put("list", new ArrayList() {{ - add("one"); - add("two"); - add("three"); - }}) - .put("body", "a quick brown fox jump over the lazy dog"); - - collection.insert(document); - } - - @Test - public void testDropAllAndCreateIndex() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("firstName")); - collection.dropAllIndices(); - assertFalse(collection.hasIndex("firstName")); - - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - assertTrue(collection.hasIndex("firstName")); - - collection = db.getCollection("test"); - assertTrue(collection.hasIndex("firstName")); - } - - @Test - public void testIssue178() { - collection.dropAllIndices(); - collection.remove(Filter.ALL); - - Document doc1 = createDocument("field", 5); - Document doc2 = createDocument("field", 4.3); - Document doc3 = createDocument("field", 0.03); - Document doc4 = createDocument("field", 4); - Document doc5 = createDocument("field", 5.0); - - collection.insert(doc1, doc2, doc3, doc4, doc5); - - DocumentCursor cursor = collection.find(where("field").eq(5)); - assertEquals(cursor.size(), 1); - - collection.createIndex("field", indexOptions(IndexType.NonUnique)); - - cursor = collection.find(where("field").eq(5)); - assertEquals(cursor.size(), 1); - } - - @Test - public void testIndexEvent() { - NitriteCollection collection = db.getCollection("index-test"); - Random random = new Random(); - for (int i = 0; i < 10000; i++) { - Document document = createDocument("first", random.nextInt()) - .put("second", random.nextDouble()); - collection.insert(document); - } - - collection.subscribe(eventInfo -> { - switch (eventInfo.getEventType()) { - case Insert: - fail("wrong event Insert"); - break; - case Update: - fail("wrong event Update"); - break; - case Remove: - fail("wrong event Remove"); - break; - case IndexStart: - case IndexEnd: - break; - } - assertTrue(eventInfo.getItem() instanceof String); - System.out.println(eventInfo.getEventType() + " for field " + eventInfo.getItem()); - }); - - collection.createIndex("first", indexOptions(IndexType.NonUnique)); - assertEquals(collection.find().size(), 10000); - - collection.createIndex("second", indexOptions(IndexType.NonUnique)); - assertEquals(collection.find().size(), 10000); - } - - @Test - public void testIndexAndSearchOnNullValues() { - NitriteCollection collection = db.getCollection("index-on-null"); - collection.insert(createDocument("first", null).put("second", 123).put("third", new Integer[]{1, 2, null})); - collection.insert(createDocument("first", "abcd").put("second", 456).put("third", new int[]{3, 1})); - collection.insert(createDocument("first", "xyz").put("second", 789).put("third", null)); - - collection.createIndex("first", indexOptions(IndexType.Unique)); - assertEquals(collection.find(where("first").eq(null)).size(), 1); - - collection.createIndex("third", indexOptions(IndexType.NonUnique)); - assertEquals(collection.find(where("third").eq(null)).size(), 2); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionInsertNegativeTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/CollectionInsertNegativeTest.java deleted file mode 100644 index 90c1ba0ef..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionInsertNegativeTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.UniqueConstraintException; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee. - */ -public class CollectionInsertNegativeTest extends BaseCollectionTest { - @Test(expected = UniqueConstraintException.class) - public void testMultipleInsert() { - WriteResult result = collection.insert(doc1, doc2, doc3); - assertEquals(result.getAffectedCount(), 3); - Document document = collection.find().firstOrNull(); - collection.insert(document); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionInsertTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/CollectionInsertTest.java deleted file mode 100644 index f7d538c31..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionInsertTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.common.WriteResult; -import org.junit.Test; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.common.Constants.DOC_ID; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -public class CollectionInsertTest extends BaseCollectionTest { - - @Test - public void testInsert() { - WriteResult result = collection.insert(doc1, doc2, doc3); - assertEquals(result.getAffectedCount(), 3); - - DocumentCursor cursor = collection.find(); - assertEquals(cursor.size(), 3); - - for (Document document : cursor) { - assertNotNull(document.get("firstName")); - assertNotNull(document.get("lastName")); - assertNotNull(document.get("birthDay")); - assertNotNull(document.get("data")); - assertNotNull(document.get("body")); - assertNotNull(document.get(DOC_ID)); - } - } - - @Test - public void testInsertHeteroDocs() { - Document document = createDocument("test", "Nitrite Test"); - - WriteResult result = collection.insert(doc1, doc2, doc3, document); - assertEquals(result.getAffectedCount(), 4); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionJoinTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/CollectionJoinTest.java deleted file mode 100644 index 2d8ef5ac5..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionJoinTest.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import lombok.extern.slf4j.Slf4j; -import org.dizitart.no2.common.Lookup; -import org.dizitart.no2.common.RecordStream; -import org.junit.Before; -import org.junit.Test; - -import java.util.Collection; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -@Slf4j -public class CollectionJoinTest extends BaseCollectionTest { - private NitriteCollection foreignCollection; - - @Before - @Override - public void setUp() { - try { - super.setUp(); - foreignCollection = db.getCollection("foreign"); - foreignCollection.remove(ALL); - - Document fdoc1 = createDocument("fName", "fn1") - .put("address", "ABCD Street") - .put("telephone", "123456789"); - - Document fdoc2 = createDocument("fName", "fn2") - .put("address", "XYZ Street") - .put("telephone", "000000000"); - - Document fdoc3 = createDocument("fName", "fn2") - .put("address", "Some other Street") - .put("telephone", "7893141321"); - - foreignCollection.insert(fdoc1, fdoc2, fdoc3); - } catch (Throwable t) { - log.error("Error while initializing test database", t); - } - } - - @Test - @SuppressWarnings("unchecked") - public void testJoinAll() { - insert(); - - Lookup lookup = new Lookup(); - lookup.setLocalField("firstName"); - lookup.setForeignField("fName"); - lookup.setTargetField("personalDetails"); - - RecordStream result = collection.find().join(foreignCollection.find(), lookup); - assertEquals(result.size(), 3); - - for (Document document : result) { - if (document.get("firstName") == "fn1") { - Collection personalDetails = (Collection) document.get("personalDetails"); - assertNotNull(personalDetails); - assertEquals(personalDetails.size(), 1); - Object[] details = personalDetails.toArray(); - assertEquals(((Document) details[0]).get("telephone"), "123456789"); - } else if (document.get("firstName") == "fn2") { - Collection personalDetails = (Collection) document.get("personalDetails"); - assertNotNull(personalDetails); - assertEquals(personalDetails.size(), 2); - Object[] details = personalDetails.toArray(); - for (Object o : details) { - Document d = (Document) o; - if (d.get("address").equals("XYZ Street")) { - assertEquals(d.get("telephone"), "000000000"); - } else { - assertEquals(d.get("telephone"), "7893141321"); - } - } - } else if (document.get("firstName") == "fn3") { - assertNull(document.get("personalDetails")); - } - System.out.println(document); - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionUpdateTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/CollectionUpdateTest.java deleted file mode 100644 index aa1c3cee7..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/CollectionUpdateTest.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection; - -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.NotIdentifiableException; -import org.dizitart.no2.exceptions.UniqueConstraintException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexType; -import org.junit.Test; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.*; - -public class CollectionUpdateTest extends BaseCollectionTest { - - @Test - public void testUpdate() { - insert(); - - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertEquals(document.get("lastName"), "ln1"); - } - - WriteResult updateResult = collection.update(where("firstName").eq("fn1"), - createDocument("lastName", "new-last-name")); - assertEquals(updateResult.getAffectedCount(), 1); - - cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertEquals(document.get("lastName"), "new-last-name"); - } - } - - @Test(expected = NotIdentifiableException.class) - public void testUpsertWithoutId() { - insert(); - Document update = createDocument("lastName", "ln4"); - WriteResult writeResult = collection.update(update, false); - assertEquals(writeResult.getAffectedCount(), 0); - assertEquals(collection.size(), 3); - } - - @Test - public void testUpsert() { - insert(); - assertEquals(collection.size(), 3); - - Document update = createDocument("lastName", "ln4"); - WriteResult writeResult = collection.update(update, true); - assertEquals(writeResult.getAffectedCount(), 1); - assertEquals(collection.size(), 4); - - Document document = collection.find(where("lastName").eq("ln4")) - .firstOrNull(); - assertTrue(isSimilar(document, update, "lastName")); - } - - @Test - public void testOptionUpsert() { - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - - WriteResult updateResult = collection.update(where("firstName").eq("fn1"), - doc1, UpdateOptions.updateOptions(true)); - assertEquals(updateResult.getAffectedCount(), 1); - - cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertTrue(isSimilar(document, doc1, "firstName", "lastName", "birthDay", "data", "list", "body")); - } - } - - @Test - public void testUpdateMultiple() { - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - - insert(); - - Document document = createDocument("lastName", "newLastName1"); - WriteResult updateResult = collection.update(where("firstName").eq("fn1").not(), - document); - assertEquals(updateResult.getAffectedCount(), 2); - - cursor = collection.find(where("lastName").eq("newLastName1")); - assertEquals(cursor.size(), 2); - } - - @Test - public void testUpdateWithOptionsUpsertFalse() { - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - - UpdateOptions updateOptions = new UpdateOptions(); - updateOptions.setInsertIfAbsent(false); - - WriteResult updateResult = collection.update(where("firstName").eq("fn1"), - doc1, updateOptions); - assertEquals(updateResult.getAffectedCount(), 0); - - cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - } - - @Test - public void testUpdateMultipleWithJustOnceFalse() { - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - - insert(); - - UpdateOptions updateOptions = new UpdateOptions(); - updateOptions.setJustOnce(false); - - Document document = createDocument("lastName", "newLastName1"); - WriteResult updateResult = collection.update(where("firstName").eq("fn1").not(), - document, updateOptions); - assertEquals(updateResult.getAffectedCount(), 2); - - cursor = collection.find(where("lastName").eq("newLastName1")); - assertEquals(cursor.size(), 2); - } - - @Test - public void testUpdateMultipleWithJustOnceTrue() { - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 0); - - insert(); - - UpdateOptions updateOptions = new UpdateOptions(); - updateOptions.setJustOnce(true); - - Document document = createDocument("lastName", "newLastName1"); - collection.update(where("firstName").eq("fn1").not(), - document, updateOptions); - } - - @Test - public void testUpdateWithNewField() { - insert(); - - DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertEquals(document.get("lastName"), "ln1"); - } - - WriteResult updateResult = collection.update(where("firstName").eq("fn1"), - createDocument("new-value", "new-value-value")); - assertEquals(updateResult.getAffectedCount(), 1); - - cursor = collection.find(where("firstName").eq("fn1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertEquals(document.get("new-value"), "new-value-value"); - } - } - - @Test - public void testUpdateInvalidFilter() { - insert(); - - DocumentCursor cursor = collection.find(where("lastName").eq("ln1")); - assertEquals(cursor.size(), 1); - for (Document document : cursor) { - assertEquals(document.get("firstName"), "fn1"); - } - - // to check if NitriteId is valid. - WriteResult updateResult = collection.update(where("some-value").eq("some-value"), - createDocument("lastName", "new-last-name")); - assertEquals(updateResult.getAffectedCount(), 0); - } - - @Test - public void updateAfterAttributeRemoval() { - NitriteCollection coll = db.getCollection("test_updateAfterAttributeRemoval"); - coll.remove(Filter.ALL); - - Document doc = createDocument().put("id", "test-1").put("group", "groupA"); - assertEquals(1, coll.insert(doc).getAffectedCount()); - - Document savedDoc1 = coll.find().firstOrNull(); - assertNotNull(savedDoc1); - - Document clonedDoc1 = savedDoc1.clone(); - assertEquals(savedDoc1, clonedDoc1); - - clonedDoc1.put("group", null); -// clonedDoc1.remove("group"); - assertEquals(1, coll.update(clonedDoc1).getAffectedCount()); - - Document savedDoc2 = coll.find(Filter.ALL).firstOrNull(); - assertNotNull(savedDoc2); - assertNull(savedDoc2.get("group")); - } - - @Test(expected = NotIdentifiableException.class) - public void testUpdateWithoutId() { - NitriteCollection collection = db.getCollection("test"); - Document document = createDocument("test", "test123"); - collection.update(document); - } - - @Test(expected = NotIdentifiableException.class) - public void testRemoveWithoutId() { - NitriteCollection collection = db.getCollection("test"); - Document document = createDocument("test", "test123"); - collection.remove(document); - } - - @Test(expected = NitriteIOException.class) - public void testRegisterListenerAfterDrop() { - NitriteCollection collection = db.getCollection("test"); - collection.drop(); - collection.subscribe(changeInfo -> fail("should not happen")); - } - - @Test(expected = NitriteIOException.class) - public void testRegisterListenerAfterClose() { - NitriteCollection collection = db.getCollection("test"); - collection.close(); - collection.subscribe(changeInfo -> fail("should not happen")); - } - - @Test(expected = UniqueConstraintException.class) - public void testIssue151() { - Document doc1 = createDocument().put("id", "test-1").put("fruit", "Apple"); - Document doc2 = createDocument().put("id", "test-2").put("fruit", "Ôrange"); - NitriteCollection coll = db.getCollection("test"); - coll.insert(doc1, doc2); - - coll.createIndex("fruit", indexOptions(IndexType.Unique)); - - assertEquals(coll.find(where("fruit").eq("Apple")).size(), 1); - - Document doc3 = coll.find(where("id").eq("test-2")).firstOrNull(); - - doc3.put("fruit", "Apple"); - coll.update(doc3); - - assertEquals(coll.find(where("fruit").eq("Apple")).size(), 1); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/DefaultNitriteCollectionTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/DefaultNitriteCollectionTest.java new file mode 100644 index 000000000..ce6d367fc --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/collection/DefaultNitriteCollectionTest.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.collection; + +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.common.concurrent.LockService; +import org.dizitart.no2.store.memory.InMemoryMap; +import org.dizitart.no2.store.memory.InMemoryStore; +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class DefaultNitriteCollectionTest { + @Test + public void testConstructor() { + InMemoryMap nitriteMap = new InMemoryMap<>("Map Name", null); + NitriteConfig nitriteConfig = mock(NitriteConfig.class); + doReturn(new InMemoryStore()).when(nitriteConfig).getNitriteStore(); + DefaultNitriteCollection actualDefaultNitriteCollection = new DefaultNitriteCollection("Name", nitriteMap, + nitriteConfig, new LockService()); + assertEquals("Name", actualDefaultNitriteCollection.getName()); + assertTrue(actualDefaultNitriteCollection.nitriteMap instanceof InMemoryMap); + assertEquals(0L, actualDefaultNitriteCollection.size()); + assertFalse(actualDefaultNitriteCollection.isDropped()); + verify(nitriteConfig, times(2)).getNitriteStore(); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/DocumentTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/DocumentTest.java similarity index 94% rename from nitrite/src/test/java/org/dizitart/no2/DocumentTest.java rename to nitrite/src/test/java/org/dizitart/no2/collection/DocumentTest.java index adef2dae3..772d71d73 100644 --- a/nitrite/src/test/java/org/dizitart/no2/DocumentTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/collection/DocumentTest.java @@ -1,47 +1,48 @@ /* - * Copyright (c) 2017-2020. Nitrite author or authors. + * Copyright (c) 2017-2021 Nitrite author or authors. * * Licensed 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 + * 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.dizitart.no2; +package org.dizitart.no2.collection; -import org.dizitart.no2.collection.Document; +import org.dizitart.no2.NitriteConfig; import org.dizitart.no2.common.tuples.Pair; import org.dizitart.no2.exceptions.InvalidIdException; import org.dizitart.no2.exceptions.ValidationException; import org.junit.After; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import java.io.*; import java.util.*; -import static org.dizitart.no2.TestUtil.parse; +import static org.dizitart.no2.integration.TestUtil.parse; import static org.dizitart.no2.collection.Document.createDocument; import static org.dizitart.no2.common.Constants.DOC_ID; import static org.dizitart.no2.common.util.Iterables.listOf; import static org.junit.Assert.*; -/** - * @author Anindya Chatterjee - */ public class DocumentTest { private Document doc; - @Rule - public Retry retry = new Retry(3); + @Test + public void testCreateDocument() { + assertTrue(((NitriteDocument) Document.createDocument()).isEmpty()); + assertEquals(1, Document.createDocument("Key", "Value").size()); + assertTrue(((NitriteDocument) Document.createDocument(new HashMap<>(1))).isEmpty()); + } @Before public void setUp() { @@ -288,3 +289,4 @@ public void testDeepRemove() { assertNull(doc.get("location.address")); } } + diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/FindOptionsTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/FindOptionsTest.java new file mode 100644 index 000000000..db71d7ff3 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/collection/FindOptionsTest.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.collection; + +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.common.SortableFields; +import org.junit.Test; + +import java.text.Collator; +import java.text.RuleBasedCollator; + +import static org.junit.Assert.*; + +public class FindOptionsTest { + @Test + public void testConstructor() { + FindOptions actualFindOptions = new FindOptions(); + actualFindOptions.limit(1L); + actualFindOptions.skip(1L); + Collator collatorResult = actualFindOptions.collator(); + assertTrue(collatorResult instanceof RuleBasedCollator); + assertEquals(1L, actualFindOptions.skip().longValue()); + assertEquals(1L, actualFindOptions.limit().longValue()); + assertNull(actualFindOptions.orderBy()); + assertEquals(0, collatorResult.getDecomposition()); + assertEquals( + "='​'=‌=‍=‎=‏=\u0000 =\u0001 =\u0002 =\u0003 =\u0004=\u0005 =\u0006 =\u0007 =\b ='\t'='\u000b' =\u000e=\u000f ='\u0010' =\u0011 =\u0012 =\u0013=\u0014 =\u0015 =\u0016 =\u0017 =\u0018=\u0019 =\u001a =\u001b =\u001c =\u001d=\u001e =\u001f" + + " ==€ = =‚ =ƒ =„ =…=† =‡ =ˆ =‰ =Š =‹=Œ = =Ž = = =‘=’ =“ =” =• =– =—=˜ =™ =š =› =œ ==ž =Ÿ;' ';' ';'" + + " ';' ';' ';' ';' ';' ';' ';' ';' ';' ';' ';' ';'';'\r' ;'\t' ;'\n" + + "';'\f';'\u000b';́;̀;̆;̂;̌;̊;̍;̈;̋;̃;̇;̄;̷;̧;̨;̣;̲;̅;̉;̎;̏;̐;̑;̒;̓;̔;̕;̖;̗;̘;̙;̚;̛;̜;̝;̞;̟;̠;̡;̢;̤;̥;̦;̩;̪;" + + "̫;̬;̭;̮;̯;̰;̱;̳;̴;̵;̶;̸;̹;̺;̻;̼;̽;̾;̿;͂;̈́;ͅ;͠;͡;҃;҄;҅;҆;⃐;⃑;⃒;⃓;⃔;⃕;⃖;⃗;⃘;⃙;⃚;⃛;⃜;⃝;⃞;⃟;⃠;⃡,'-';­;‐;" + + "‑;‒;–;—;―;−<'_'<¯<','<';'<':'<'!'<¡<'?'<¿<'/'<'.'<´<'`'<'^'<¨<'~'<·<¸<'''<'\"'<«<»<'('<')'<'['<']'<'{" + + "'<'}'<§<¶<©<®<'@'<¤<฿<¢<₡<₢<'$'<₫<€<₣<₤<₥<₦<₧<£<₨<₪<₩<¥<'*'<'\\'<'&'<'#'<'%'<'+'<±<÷<×<'<'<'='<'>'<¬<" + + "'|'<¦<°<µ<0<1<2<3<4<5<6<7<8<9<¼<½<¾get(null, type)); + assertNull((new NitriteDocument()).get(null, type)); + assertNull((new NitriteDocument()).get("Field")); + assertNull((new NitriteDocument()).get(null)); + assertNull((new NitriteDocument()).get("java.io.Serializable")); } @Test public void testGet2() { - Class type = Object.class; - assertNull((new NitriteDocument()).get("key", type)); + NitriteDocument nitriteDocument = new NitriteDocument(); + nitriteDocument.put("java.io.Serializable", "Value"); + assertEquals("Value", nitriteDocument.get("java.io.Serializable")); } @Test public void testGet3() { - assertNull((new NitriteDocument()).get("key")); + NitriteDocument nitriteDocument = new NitriteDocument(); + assertNull(nitriteDocument.get("Field", Object.class)); + } + + @Test + public void testGet4() { + NitriteDocument nitriteDocument = new NitriteDocument(); + assertNull(nitriteDocument.get(null, Object.class)); + } + + @Test + public void testGetId() { + NitriteDocument nitriteDocument = new NitriteDocument(); + nitriteDocument.putIfAbsent("_id", "42"); + assertEquals("42", nitriteDocument.getId().getIdValue()); + } + + @Test + public void testGetId2() { + NitriteDocument nitriteDocument = new NitriteDocument(); + nitriteDocument.put("_id", 42); + assertThrows(InvalidIdException.class, nitriteDocument::getId); } @Test public void testGetFields() { + assertTrue((new NitriteDocument()).getFields().isEmpty()); + NitriteDocument nitriteDocument = new NitriteDocument(); nitriteDocument.put("foo", "foo"); Set actualFields = nitriteDocument.getFields(); @@ -65,7 +94,25 @@ public void testGetFields3() { @Test public void testGetFields4() { - assertEquals(0, (new NitriteDocument()).getFields().size()); + NitriteDocument nitriteDocument = new NitriteDocument(); + nitriteDocument.putIfAbsent("", new NitriteDocument()); + assertTrue(nitriteDocument.getFields().isEmpty()); + } + + @Test + public void testGetFields5() { + NitriteDocument nitriteDocument = new NitriteDocument(); + nitriteDocument.putIfAbsent("", new ArrayList()); + assertTrue(nitriteDocument.getFields().isEmpty()); + } + + @Test + public void testGetFields6() { + NitriteDocument nitriteDocument = new NitriteDocument(); + nitriteDocument.put("java.io.Serializable", "Value"); + Set actualFields = nitriteDocument.getFields(); + assertEquals(1, actualFields.size()); + assertTrue(actualFields.contains("java.io.Serializable")); } @Test @@ -73,11 +120,32 @@ public void testHasId() { assertFalse((new NitriteDocument()).hasId()); } + @Test + public void testHasId2() { + NitriteDocument nitriteDocument = new NitriteDocument(); + nitriteDocument.putIfAbsent("_id", "42"); + assertTrue(nitriteDocument.hasId()); + } + @Test public void testClone() { assertEquals(0, (new NitriteDocument()).clone().size()); } + @Test + public void testClone2() { + NitriteDocument nitriteDocument = new NitriteDocument(); + nitriteDocument.put("Field", "Value"); + assertEquals(1, nitriteDocument.clone().size()); + } + + @Test + public void testClone3() { + NitriteDocument nitriteDocument = new NitriteDocument(); + nitriteDocument.put("Field", new NitriteDocument()); + assertEquals(1, nitriteDocument.clone().size()); + } + @Test public void testContainsKey() { assertFalse((new NitriteDocument()).containsKey("key")); @@ -85,20 +153,80 @@ public void testContainsKey() { @Test public void testEquals() { - NitriteDocument nitriteDocument = new NitriteDocument(); - nitriteDocument.put("foo", "foo"); - assertFalse(nitriteDocument.equals(new NitriteDocument())); + assertFalse((new NitriteDocument()).equals("Other")); } @Test public void testEquals2() { - assertFalse((new NitriteDocument()).equals("other")); + NitriteDocument nitriteDocument = new NitriteDocument(); + assertTrue(nitriteDocument.equals(new NitriteDocument())); } @Test public void testEquals3() { NitriteDocument nitriteDocument = new NitriteDocument(); - assertTrue(nitriteDocument.equals(new NitriteDocument())); + nitriteDocument.put("Field", "Value"); + assertFalse(nitriteDocument.equals(new NitriteDocument())); + } + + @Test + public void testEquals4() { + NitriteDocument nitriteDocument = new NitriteDocument(); + nitriteDocument.put("Field", "Value"); + + NitriteDocument nitriteDocument1 = new NitriteDocument(); + nitriteDocument1.put("Field", "Value"); + assertTrue(nitriteDocument.equals(nitriteDocument1)); + } + + @Test + public void testEquals5() { + NitriteDocument nitriteDocument = new NitriteDocument(); + nitriteDocument.put("Field", "Value"); + + NitriteDocument nitriteDocument1 = new NitriteDocument(); + nitriteDocument1.putIfAbsent("foo", "42"); + assertFalse(nitriteDocument.equals(nitriteDocument1)); + } + + @Test + public void testEquals6() { + NitriteDocument nitriteDocument = new NitriteDocument(); + nitriteDocument.put("Field", null); + + NitriteDocument nitriteDocument1 = new NitriteDocument(); + nitriteDocument1.put("Field", "Value"); + assertFalse(nitriteDocument.equals(nitriteDocument1)); + } + + @Test + public void testEquals7() { + NitriteDocument nitriteDocument = new NitriteDocument(); + nitriteDocument.put("Field", new NitriteDocument()); + + NitriteDocument nitriteDocument1 = new NitriteDocument(); + nitriteDocument1.put("Field", "Value"); + assertFalse(nitriteDocument.equals(nitriteDocument1)); + } + + @Test + public void testEquals8() { + NitriteDocument nitriteDocument = new NitriteDocument(); + nitriteDocument.put("Field", null); + + NitriteDocument nitriteDocument1 = new NitriteDocument(); + nitriteDocument1.putIfAbsent("foo", "42"); + assertFalse(nitriteDocument.equals(nitriteDocument1)); + } + + @Test + public void testEquals9() { + NitriteDocument nitriteDocument = new NitriteDocument(); + nitriteDocument.put("Field", null); + + NitriteDocument nitriteDocument1 = new NitriteDocument(); + nitriteDocument1.put("Field", null); + assertTrue(nitriteDocument.equals(nitriteDocument1)); } } diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/NitriteIdTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/NitriteIdTest.java index a12bcc714..6ff816554 100644 --- a/nitrite/src/test/java/org/dizitart/no2/collection/NitriteIdTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/collection/NitriteIdTest.java @@ -6,9 +6,69 @@ import static org.junit.Assert.*; public class NitriteIdTest { + @Test + public void testLimit() { + NitriteId one = NitriteId.createId(Long.toString(Long.MAX_VALUE)); + NitriteId two = NitriteId.createId(Long.toString(Long.MIN_VALUE)); + assertEquals(one.compareTo(two), 1); + } + + @Test + public void testHashEquals() { + NitriteId one = NitriteId.createId("1"); + NitriteId two = NitriteId.createId("1"); + + assertEquals(one, two); + assertEquals(one.hashCode(), two.hashCode()); + + NitriteId third = NitriteId.createId("2"); + assertNotEquals(one, third); + assertNotEquals(one.hashCode(), third.hashCode()); + } + + @Test + public void testCompare() { + NitriteId one = NitriteId.createId("1"); + NitriteId two = NitriteId.createId("2"); + NitriteId three = NitriteId.createId("3"); + + assertEquals(one.compareTo(two), -1); + assertEquals(three.compareTo(one), 1); + + one = NitriteId.createId("10"); + two = NitriteId.createId("20"); + assertEquals(one.compareTo(two), -1); + + one = NitriteId.newId(); + two = NitriteId.newId(); + + assertFalse(one.compareTo(two) == 0); + } + + @Test(expected = InvalidIdException.class) + public void testToString() { + NitriteId nullId = NitriteId.createId(null); + assertNotEquals(nullId.toString(), ""); + } + + @Test(expected = InvalidIdException.class) + public void testCompareNull() { + NitriteId first = NitriteId.newId(); + NitriteId second = NitriteId.createId(null); + assertEquals(first.compareTo(second), 1); + } + + @Test + public void testCreateId() { + assertEquals("42", NitriteId.createId("42").getIdValue()); + assertThrows(InvalidIdException.class, () -> NitriteId.createId(null)); + assertThrows(InvalidIdException.class, () -> NitriteId.createId("Value")); + } + @Test public void testValidId() { - assertThrows(InvalidIdException.class, () -> NitriteId.validId("value")); + assertThrows(InvalidIdException.class, () -> NitriteId.validId("Value")); + assertThrows(InvalidIdException.class, () -> NitriteId.validId(null)); assertTrue(NitriteId.validId(42)); } @@ -17,5 +77,28 @@ public void testCompareTo() { NitriteId newIdResult = NitriteId.newId(); assertEquals(-1, newIdResult.compareTo(NitriteId.newId())); } + + @Test + public void testCompareTo2() { + NitriteId newIdResult = NitriteId.newId(); + assertEquals(1, newIdResult.compareTo(NitriteId.createId("42"))); + } + + @Test + public void testEquals() { + assertFalse(NitriteId.newId().equals("42")); + } + + @Test + public void testEquals2() { + NitriteId newIdResult = NitriteId.newId(); + assertFalse(newIdResult.equals(NitriteId.newId())); + } + + @Test + public void testEquals3() { + NitriteId createIdResult = NitriteId.createId("42"); + assertTrue(createIdResult.equals(NitriteId.createId("42"))); + } } diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/SnowflakeIdGeneratorTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/SnowflakeIdGeneratorTest.java new file mode 100644 index 000000000..5c0273aa4 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/collection/SnowflakeIdGeneratorTest.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.collection; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class SnowflakeIdGeneratorTest { + + @Test + public void testTillNextMillis() { + assertTrue((new SnowflakeIdGenerator()).tillNextMillis(1L) > 1); + } + + @Test + public void testGetId() { + assertTrue((new SnowflakeIdGenerator()).getId() != 0); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/operation/BoundedDocumentStreamTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/operation/BoundedDocumentStreamTest.java deleted file mode 100644 index c2fb18495..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/operation/BoundedDocumentStreamTest.java +++ /dev/null @@ -1,87 +0,0 @@ -package org.dizitart.no2.collection.operation; - -import com.fasterxml.jackson.databind.util.ArrayIterator; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.filters.Filter; -import org.junit.Test; - -import java.util.NoSuchElementException; - -import static org.junit.Assert.*; - -public class BoundedDocumentStreamTest { - @Test - public void testBoundedIteratorHasNext() { - assertTrue( - (new BoundedDocumentStream.BoundedIterator<>(new ArrayIterator<>(new Object[]{"foo", "foo", "foo"}), - 1L, 3L)).hasNext()); - } - - @Test - public void testBoundedIteratorNext() { - assertEquals("foo", (new BoundedDocumentStream.BoundedIterator<>(new BoundedDocumentStream.BoundedIterator<>( - new ArrayIterator<>(new Object[]{"foo", "foo", "foo"}), 1L, 3L), 1L, 3L)).next()); - assertEquals("foo", - (new BoundedDocumentStream.BoundedIterator<>(new ArrayIterator<>(new Object[]{"foo", "foo", "foo"}), - 1L, 3L)).next()); - assertThrows(NoSuchElementException.class, () -> (new BoundedDocumentStream.BoundedIterator<>( - new ArrayIterator<>(new Object[]{"foo", "foo", "foo"}), 1L, 0L)).next()); - } - - @Test - public void testConstructor() { - FilteredRecordStream recordStream = new FilteredRecordStream(null, null); - FilteredRecordStream recordStream1 = new FilteredRecordStream(recordStream, Filter.byId(NitriteId.newId())); - FilteredRecordStream recordStream2 = new FilteredRecordStream(recordStream1, Filter.byId(NitriteId.newId())); - assertTrue( - (new BoundedDocumentStream(new FilteredRecordStream(recordStream2, Filter.byId(NitriteId.newId())), 1L, 1L)) - .isEmpty()); - } - - @Test - public void testConstructor2() { - FilteredRecordStream recordStream = new FilteredRecordStream(null, null); - FilteredRecordStream recordStream1 = new FilteredRecordStream(recordStream, Filter.byId(NitriteId.newId())); - FilteredRecordStream recordStream2 = new FilteredRecordStream(recordStream1, Filter.byId(NitriteId.newId())); - assertThrows(ValidationException.class, - () -> new BoundedDocumentStream(new FilteredRecordStream(recordStream2, Filter.byId(NitriteId.newId())), -1L, - 1L)); - } - - @Test - public void testConstructor3() { - FilteredRecordStream recordStream = new FilteredRecordStream(null, null); - FilteredRecordStream recordStream1 = new FilteredRecordStream(recordStream, Filter.byId(NitriteId.newId())); - FilteredRecordStream recordStream2 = new FilteredRecordStream(recordStream1, Filter.byId(NitriteId.newId())); - assertThrows(ValidationException.class, - () -> new BoundedDocumentStream(new FilteredRecordStream(recordStream2, Filter.byId(NitriteId.newId())), 1L, - -1L)); - } - - @Test - public void testIterator() { - assertTrue((new BoundedDocumentStream(null, 1L, 1L)).iterator() instanceof BoundedDocumentStream.BoundedIterator); - } - - @Test - public void testIterator2() { - FilteredRecordStream recordStream = new FilteredRecordStream(null, null); - FilteredRecordStream recordStream1 = new FilteredRecordStream(recordStream, Filter.byId(NitriteId.newId())); - BoundedDocumentStream recordStream2 = new BoundedDocumentStream( - new FilteredRecordStream(recordStream1, Filter.byId(NitriteId.newId())), 1L, 1L); - assertTrue( - (new BoundedDocumentStream(new FilteredRecordStream(recordStream2, Filter.byId(NitriteId.newId())), 1L, 1L)) - .iterator() instanceof BoundedDocumentStream.BoundedIterator); - } - - @Test - public void testIterator3() { - FilteredRecordStream recordStream = new FilteredRecordStream(null, null); - FilteredRecordStream recordStream1 = new FilteredRecordStream(recordStream, Filter.byId(NitriteId.newId())); - assertTrue( - (new BoundedDocumentStream(new FilteredRecordStream(recordStream1, Filter.byId(NitriteId.newId())), 1L, 1L)) - .iterator() instanceof BoundedDocumentStream.BoundedIterator); - } -} - diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/operation/CollectionOperationsTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/operation/CollectionOperationsTest.java new file mode 100644 index 000000000..7200ec7fc --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/collection/operation/CollectionOperationsTest.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.collection.operation; + +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.store.memory.InMemoryMap; +import org.dizitart.no2.store.memory.InMemoryStore; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; + +public class CollectionOperationsTest { + @Test + public void testConstructor() { + InMemoryMap nitriteMap = new InMemoryMap<>("Map Name", null); + NitriteConfig nitriteConfig = mock(NitriteConfig.class); + doReturn(new InMemoryStore()).when(nitriteConfig).getNitriteStore(); + assertEquals(0L, (new CollectionOperations("Collection Name", nitriteMap, nitriteConfig, null)).getSize()); + verify(nitriteConfig).getNitriteStore(); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/operation/DocumentCursorImplTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/operation/DocumentCursorImplTest.java deleted file mode 100644 index dfbed7a04..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/operation/DocumentCursorImplTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.dizitart.no2.collection.operation; - -import static org.junit.Assert.assertTrue; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.Lookup; -import org.dizitart.no2.common.NullOrder; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.filters.Filter; -import org.junit.Test; - -public class DocumentCursorImplTest { - @Test - public void testSort() { - FilteredRecordStream recordStream = new FilteredRecordStream(null, null); - FilteredRecordStream recordStream1 = new FilteredRecordStream(recordStream, Filter.byId(NitriteId.newId())); - assertTrue((new DocumentCursorImpl(new FilteredRecordStream(recordStream1, Filter.byId(NitriteId.newId())))) - .sort("field", SortOrder.Ascending, null, NullOrder.First).isEmpty()); - } - - @Test - public void testSkipLimit() { - FilteredRecordStream recordStream = new FilteredRecordStream(null, null); - FilteredRecordStream recordStream1 = new FilteredRecordStream(recordStream, Filter.byId(NitriteId.newId())); - assertTrue((new DocumentCursorImpl(new FilteredRecordStream(recordStream1, Filter.byId(NitriteId.newId())))) - .skipLimit(1L, 1L).isEmpty()); - } - - @Test - public void testProject() { - FilteredRecordStream recordStream = new FilteredRecordStream(null, null); - FilteredRecordStream recordStream1 = new FilteredRecordStream(recordStream, Filter.byId(NitriteId.newId())); - DocumentCursorImpl documentCursorImpl = new DocumentCursorImpl( - new FilteredRecordStream(recordStream1, Filter.byId(NitriteId.newId()))); - assertTrue(documentCursorImpl.project(Document.createDocument()).isEmpty()); - } - - @Test - public void testJoin() { - FilteredRecordStream recordStream = new FilteredRecordStream(null, null); - FilteredRecordStream recordStream1 = new FilteredRecordStream(recordStream, Filter.byId(NitriteId.newId())); - DocumentCursorImpl documentCursorImpl = new DocumentCursorImpl( - new FilteredRecordStream(recordStream1, Filter.byId(NitriteId.newId()))); - FilteredRecordStream recordStream2 = new FilteredRecordStream(null, null); - FilteredRecordStream recordStream3 = new FilteredRecordStream(recordStream2, Filter.byId(NitriteId.newId())); - DocumentCursorImpl foreignCursor = new DocumentCursorImpl( - new FilteredRecordStream(recordStream3, Filter.byId(NitriteId.newId()))); - assertTrue(documentCursorImpl.join(foreignCursor, new Lookup()).isEmpty()); - } -} - diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/operation/DocumentCursorTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/operation/DocumentCursorTest.java deleted file mode 100644 index bc23b70e5..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/operation/DocumentCursorTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection.operation; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.Retry; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.DocumentCursor; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.util.Iterator; - -import static org.dizitart.no2.TestUtil.createDb; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee. - */ -public class DocumentCursorTest { - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testFindResult() { - db = createDb(); - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("first", "second")); - - DocumentCursor result = collection.find(); - assertTrue(result instanceof DocumentCursorImpl); - } - - @Test(expected = InvalidOperationException.class) - public void testIteratorRemove() { - db = createDb(); - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("first", "second")); - - DocumentCursor cursor = collection.find(); - Iterator iterator = cursor.iterator(); - if (iterator.hasNext()) { - iterator.next(); - iterator.remove(); - } - } - - @Test - public void testValidateProjection() { - db = createDb(); - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("first", "second")); - - Document projection = createDocument("first", createDocument("second", null)); - RecordStream project = collection.find().project(projection); - assertNotNull(project); - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/operation/DocumentIndexWriterTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/operation/DocumentIndexWriterTest.java new file mode 100644 index 000000000..827dec075 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/collection/operation/DocumentIndexWriterTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.collection.operation; + +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.index.UniqueIndexer; +import org.dizitart.no2.store.memory.InMemoryStore; +import org.junit.Test; + +import java.util.ArrayList; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.mockito.Mockito.*; + +public class DocumentIndexWriterTest { + + @Test + public void testWriteIndexEntry() { + ArrayList indexDescriptorList = new ArrayList<>(); + indexDescriptorList.add(new IndexDescriptor(IndexType.UNIQUE, Fields.withNames("a"), "Collection Name")); + IndexOperations indexOperations = mock(IndexOperations.class); + when(indexOperations.listIndexes()).thenReturn(indexDescriptorList); + NitriteConfig nitriteConfig = mock(NitriteConfig.class); + doReturn(new UniqueIndexer()).when(nitriteConfig).findIndexer(IndexType.UNIQUE); + doReturn(new InMemoryStore()).when(nitriteConfig).getNitriteStore(); + + (new DocumentIndexWriter(nitriteConfig, indexOperations)).writeIndexEntry(createDocument("a", 1)); + verify(indexOperations).listIndexes(); + } + + @Test + public void testRemoveIndexEntry() { + ArrayList indexDescriptorList = new ArrayList<>(); + indexDescriptorList.add(new IndexDescriptor(IndexType.UNIQUE, Fields.withNames("a"), "Collection Name")); + IndexOperations indexOperations = mock(IndexOperations.class); + when(indexOperations.listIndexes()).thenReturn(indexDescriptorList); + NitriteConfig nitriteConfig = mock(NitriteConfig.class); + doReturn(new UniqueIndexer()).when(nitriteConfig).findIndexer(IndexType.UNIQUE); + doReturn(new InMemoryStore()).when(nitriteConfig).getNitriteStore(); + (new DocumentIndexWriter(nitriteConfig, indexOperations)).removeIndexEntry(createDocument("a", 1)); + verify(indexOperations).listIndexes(); + } + + @Test + public void testUpdateIndexEntry() { + ArrayList indexDescriptorList = new ArrayList<>(); + indexDescriptorList.add(new IndexDescriptor(IndexType.UNIQUE, Fields.withNames("a"), "Collection Name")); + IndexOperations indexOperations = mock(IndexOperations.class); + when(indexOperations.listIndexes()).thenReturn(indexDescriptorList); + NitriteConfig nitriteConfig = mock(NitriteConfig.class); + doReturn(new UniqueIndexer()).when(nitriteConfig).findIndexer(IndexType.UNIQUE); + doReturn(new InMemoryStore()).when(nitriteConfig).getNitriteStore(); + + (new DocumentIndexWriter(nitriteConfig, indexOperations)).updateIndexEntry(createDocument("a", 1), createDocument("a", 2)); + verify(indexOperations).listIndexes(); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/operation/FilteredRecordStreamTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/operation/FilteredRecordStreamTest.java deleted file mode 100644 index 00ee32675..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/operation/FilteredRecordStreamTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.dizitart.no2.collection.operation; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import com.fasterxml.jackson.databind.util.ArrayIterator; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.filters.Filter; -import org.junit.Test; - -public class FilteredRecordStreamTest { - @Test - public void testFilteredIteratorHasNext() { - ArrayIterator> iterator = new ArrayIterator>(new Pair[]{}); - FilteredRecordStream.FilteredIterator iterator1 = new FilteredRecordStream.FilteredIterator(iterator, - Filter.byId(NitriteId.newId())); - assertFalse((new FilteredRecordStream.FilteredIterator(iterator1, Filter.byId(NitriteId.newId()))).hasNext()); - } - - @Test - public void testIterator() { - FilteredRecordStream recordStream = new FilteredRecordStream(null, null); - FilteredRecordStream recordStream1 = new FilteredRecordStream(recordStream, Filter.byId(NitriteId.newId())); - FilteredRecordStream recordStream2 = new FilteredRecordStream(recordStream1, Filter.byId(NitriteId.newId())); - assertTrue((new FilteredRecordStream(recordStream2, Filter.byId(NitriteId.newId()))) - .iterator() instanceof FilteredRecordStream.FilteredIterator); - } - - @Test - public void testFilteredIteratorHasNext2() { - Pair pair = new Pair(); - pair.setSecond(Document.createDocument()); - ArrayIterator> iterator = new ArrayIterator>(new Pair[]{pair}); - assertFalse((new FilteredRecordStream.FilteredIterator(iterator, Filter.byId(NitriteId.newId()))).hasNext()); - } - - @Test - public void testFilteredIteratorHasNext3() { - ArrayIterator> iterator = new ArrayIterator>(new Pair[]{}); - assertFalse((new FilteredRecordStream.FilteredIterator(iterator, Filter.byId(NitriteId.newId()))).hasNext()); - } -} - diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/operation/FindOptimizerTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/operation/FindOptimizerTest.java new file mode 100644 index 000000000..a41bfea7f --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/collection/operation/FindOptimizerTest.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.collection.operation; + +import org.dizitart.no2.collection.FindOptions; +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexDescriptor; +import org.junit.Test; + +import java.util.ArrayList; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; + +public class FindOptimizerTest { + @Test + public void testOptimize() { + FindOptimizer findOptimizer = new FindOptimizer(); + Filter filter = mock(Filter.class); + FindOptions findOptions = new FindOptions(); + FindPlan actualOptimizeResult = findOptimizer.optimize(filter, findOptions, new ArrayList()); + assertTrue(actualOptimizeResult.getBlockingSortOrder().isEmpty()); + assertTrue(actualOptimizeResult.getSubPlans().isEmpty()); + assertNull(actualOptimizeResult.getSkip()); + assertNull(actualOptimizeResult.getLimit()); + } + + @Test + public void testOptimize2() { + FindOptimizer findOptimizer = new FindOptimizer(); + FindOptions findOptions = new FindOptions(); + FindPlan actualOptimizeResult = findOptimizer.optimize(null, findOptions, new ArrayList()); + assertTrue(actualOptimizeResult.getBlockingSortOrder().isEmpty()); + assertTrue(actualOptimizeResult.getSubPlans().isEmpty()); + assertNull(actualOptimizeResult.getSkip()); + assertNull(actualOptimizeResult.getLimit()); + } + + @Test + public void testOptimize3() { + FindOptimizer findOptimizer = new FindOptimizer(); + Filter filter = mock(Filter.class); + FindPlan actualOptimizeResult = findOptimizer.optimize(filter, null, new ArrayList()); + assertTrue(actualOptimizeResult.getBlockingSortOrder().isEmpty()); + assertTrue(actualOptimizeResult.getSubPlans().isEmpty()); + } + + @Test + public void testOptimize4() { + FindOptimizer findOptimizer = new FindOptimizer(); + Filter filter = mock(Filter.class); + FindOptions findOptions = FindOptions.orderBy("Field Name", SortOrder.Ascending); + FindPlan actualOptimizeResult = findOptimizer.optimize(filter, findOptions, new ArrayList()); + assertEquals(1, actualOptimizeResult.getBlockingSortOrder().size()); + assertTrue(actualOptimizeResult.getSubPlans().isEmpty()); + assertNull(actualOptimizeResult.getSkip()); + assertNull(actualOptimizeResult.getLimit()); + } + + @Test + public void testOptimize5() { + FindOptimizer findOptimizer = new FindOptimizer(); + Filter filter = mock(Filter.class); + FindOptions findOptions = new FindOptions(); + + ArrayList indexDescriptorList = new ArrayList(); + indexDescriptorList.add(new IndexDescriptor("Index Type", new Fields(), "Collection Name")); + FindPlan actualOptimizeResult = findOptimizer.optimize(filter, findOptions, indexDescriptorList); + assertTrue(actualOptimizeResult.getBlockingSortOrder().isEmpty()); + assertTrue(actualOptimizeResult.getSubPlans().isEmpty()); + assertNull(actualOptimizeResult.getSkip()); + assertNull(actualOptimizeResult.getLimit()); + } + + @Test + public void testOptimize6() { + FindOptimizer findOptimizer = new FindOptimizer(); + Filter filter = mock(Filter.class); + FindOptions findOptions = new FindOptions(); + + Fields fields = new Fields(); + fields.addField("Field"); + IndexDescriptor e = new IndexDescriptor("Index Type", fields, "Collection Name"); + + ArrayList indexDescriptorList = new ArrayList(); + indexDescriptorList.add(e); + FindPlan actualOptimizeResult = findOptimizer.optimize(filter, findOptions, indexDescriptorList); + assertTrue(actualOptimizeResult.getBlockingSortOrder().isEmpty()); + assertTrue(actualOptimizeResult.getSubPlans().isEmpty()); + assertNull(actualOptimizeResult.getSkip()); + assertNull(actualOptimizeResult.getLimit()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/operation/IndexManagerTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/operation/IndexManagerTest.java new file mode 100644 index 000000000..3769b47fd --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/collection/operation/IndexManagerTest.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.collection.operation; + +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.store.memory.InMemoryStore; +import org.junit.Test; + +import static org.mockito.Mockito.*; + +public class IndexManagerTest { + @Test + public void testConstructor() { + NitriteConfig nitriteConfig = mock(NitriteConfig.class); + doReturn(new InMemoryStore()).when(nitriteConfig).getNitriteStore(); + new IndexManager("Collection Name", nitriteConfig); + verify(nitriteConfig).getNitriteStore(); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/operation/IndexedStreamTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/operation/IndexedStreamTest.java deleted file mode 100644 index 7915683e8..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/operation/IndexedStreamTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.dizitart.no2.collection.operation; - -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import com.fasterxml.jackson.databind.util.ArrayIterator; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.store.memory.InMemoryMap; -import org.junit.Test; - -public class IndexedStreamTest { - @Test - public void testIndexedStreamIteratorHasNext() { - NitriteId newIdResult = NitriteId.newId(); - NitriteId newIdResult1 = NitriteId.newId(); - ArrayIterator iterator = new ArrayIterator( - new NitriteId[]{newIdResult, newIdResult1, NitriteId.newId()}); - assertTrue( - (new IndexedStream.IndexedStreamIterator(iterator, new InMemoryMap("mapName", null))) - .hasNext()); - } - - @Test - public void testIndexedStreamIteratorNext() { - NitriteId newIdResult = NitriteId.newId(); - NitriteId newIdResult1 = NitriteId.newId(); - ArrayIterator iterator = new ArrayIterator( - new NitriteId[]{newIdResult, newIdResult1, NitriteId.newId()}); - IndexedStream.IndexedStreamIterator indexedStreamIterator = new IndexedStream.IndexedStreamIterator(iterator, - new InMemoryMap("mapName", null)); - assertNull(indexedStreamIterator.next().getSecond()); - assertTrue(indexedStreamIterator.hasNext()); - } -} - diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/operation/JoinedDocumentStreamTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/operation/JoinedDocumentStreamTest.java deleted file mode 100644 index 1e950eae4..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/operation/JoinedDocumentStreamTest.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.collection.operation; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.Retry; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.Lookup; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.filters.Filter; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; - -import java.util.Iterator; - -import static org.dizitart.no2.TestUtil.createDb; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -/** - * @author Anindya Chatterjee - */ -public class JoinedDocumentStreamTest { - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Test - public void testFindResult() { - db = createDb(); - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("first", "second")); - - RecordStream result = collection.find().join(collection.find(), new Lookup()); - assertTrue(result instanceof JoinedDocumentStream); - } - - @Test(expected = InvalidOperationException.class) - public void testIteratorRemove() { - db = createDb(); - NitriteCollection collection = db.getCollection("test"); - collection.insert(createDocument("first", "second")); - - RecordStream cursor = collection.find().join(collection.find(), new Lookup()); - assertNotNull(cursor.toString()); - Iterator iterator = cursor.iterator(); - if (iterator.hasNext()) { - iterator.next(); - iterator.remove(); - } - } - - @Test - public void testToString() { - FilteredRecordStream recordStream = new FilteredRecordStream(null, null); - FilteredRecordStream recordStream1 = new FilteredRecordStream(recordStream, Filter.byId(NitriteId.newId())); - FilteredRecordStream recordStream2 = new FilteredRecordStream(recordStream1, Filter.byId(NitriteId.newId())); - FilteredRecordStream recordStream3 = new FilteredRecordStream(null, null); - DocumentCursorImpl foreignCursor = new DocumentCursorImpl( - new FilteredRecordStream(recordStream3, Filter.byId(NitriteId.newId()))); - assertEquals("[]", (new JoinedDocumentStream(recordStream2, foreignCursor, new Lookup())).toString()); - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/operation/ProjectedDocumentStreamTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/operation/ProjectedDocumentStreamTest.java deleted file mode 100644 index 5fc934208..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/operation/ProjectedDocumentStreamTest.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.dizitart.no2.collection.operation; - -import static org.junit.Assert.assertEquals; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.filters.Filter; -import org.junit.Test; - -public class ProjectedDocumentStreamTest { - @Test - public void testToString() { - assertEquals("[]", (new ProjectedDocumentStream(null, Document.createDocument())).toString()); - } - - @Test - public void testToString2() { - FilteredRecordStream recordStream = new FilteredRecordStream(null, null); - FilteredRecordStream recordStream1 = new FilteredRecordStream(recordStream, Filter.byId(NitriteId.newId())); - FilteredRecordStream recordStream2 = new FilteredRecordStream(recordStream1, Filter.byId(NitriteId.newId())); - assertEquals("[]", (new ProjectedDocumentStream(recordStream2, Document.createDocument())).toString()); - } -} - diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/operation/ReadOperationsTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/operation/ReadOperationsTest.java index b9ef64bf4..bbb99823d 100644 --- a/nitrite/src/test/java/org/dizitart/no2/collection/operation/ReadOperationsTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/collection/operation/ReadOperationsTest.java @@ -1,31 +1,78 @@ -package org.dizitart.no2.collection.operation; +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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. + * + */ -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +package org.dizitart.no2.collection.operation; import org.dizitart.no2.NitriteConfig; import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.FindOptions; import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.common.processors.ProcessorChain; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexDescriptor; import org.dizitart.no2.store.memory.InMemoryMap; import org.junit.Test; +import java.util.ArrayList; + +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.*; + public class ReadOperationsTest { + @Test public void testFind() { - InMemoryMap nitriteMap = new InMemoryMap("mapName", null); - assertTrue((new ReadOperations("collectionName", new NitriteConfig(), nitriteMap, null)).find().isEmpty()); + IndexOperations indexOperations = mock(IndexOperations.class); + when(indexOperations.listIndexes()).thenReturn(new ArrayList<>()); + NitriteConfig nitriteConfig = new NitriteConfig(); + InMemoryMap nitriteMap = new InMemoryMap<>("Map Name", null); + + ReadOperations readOperations = new ReadOperations("Collection Name", indexOperations, nitriteConfig, nitriteMap, + new ProcessorChain()); + Filter filter = mock(Filter.class); + assertTrue(readOperations.find(filter, new FindOptions()).toList().isEmpty()); + verify(indexOperations).listIndexes(); } @Test public void testFind2() { - InMemoryMap nitriteMap = new InMemoryMap("mapName", null); - assertTrue((new ReadOperations("collectionName", new NitriteConfig(), nitriteMap, null)).find(null).isEmpty()); + ArrayList indexDescriptorList = new ArrayList<>(); + indexDescriptorList.add(new IndexDescriptor("Index Type", new Fields(), "Collection Name")); + IndexOperations indexOperations = mock(IndexOperations.class); + when(indexOperations.listIndexes()).thenReturn(indexDescriptorList); + NitriteConfig nitriteConfig = new NitriteConfig(); + InMemoryMap nitriteMap = new InMemoryMap<>("Map Name", null); + + ReadOperations readOperations = new ReadOperations("Collection Name", indexOperations, nitriteConfig, nitriteMap, + new ProcessorChain()); + Filter filter = mock(Filter.class); + assertTrue(readOperations.find(filter, new FindOptions()).toList().isEmpty()); + verify(indexOperations).listIndexes(); } @Test public void testGetById() { - InMemoryMap nitriteMap = new InMemoryMap("mapName", null); - ReadOperations readOperations = new ReadOperations("collectionName", new NitriteConfig(), nitriteMap, null); + NitriteConfig nitriteConfig = new NitriteConfig(); + InMemoryMap nitriteMap = new InMemoryMap<>("Map Name", null); + + ReadOperations readOperations = new ReadOperations("Collection Name", null, nitriteConfig, nitriteMap, + new ProcessorChain()); assertNull(readOperations.getById(NitriteId.newId())); } } diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/operation/SortedDocumentCursorTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/operation/SortedDocumentCursorTest.java deleted file mode 100644 index 7af703783..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/operation/SortedDocumentCursorTest.java +++ /dev/null @@ -1,123 +0,0 @@ -package org.dizitart.no2.collection.operation; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertSame; - -import com.fasterxml.jackson.databind.util.ArrayIterator; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.NullOrder; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.filters.Filter; -import org.junit.Test; - -public class SortedDocumentCursorTest { - @Test - public void testIterator() { - assertFalse( - (new SortedDocumentCursor("field", SortOrder.Ascending, null, NullOrder.First, null)).iterator().hasNext()); - } - - @Test - public void testIterator2() { - FilteredRecordStream recordStream = new FilteredRecordStream(null, null); - FilteredRecordStream recordStream1 = new FilteredRecordStream(recordStream, Filter.byId(NitriteId.newId())); - assertFalse((new SortedDocumentCursor("field", SortOrder.Ascending, null, NullOrder.First, - new FilteredRecordStream(recordStream1, Filter.byId(NitriteId.newId())))).iterator().hasNext()); - } - - @Test - public void testSortedDocumentIteratorConstructor() { - Pair pair = new Pair(); - Pair pair1 = new Pair(); - ArrayIterator> arrayIterator = new ArrayIterator>( - new Pair[]{pair, pair1, new Pair()}); - assertFalse((new SortedDocumentCursor.SortedDocumentIterator("field", null, null, NullOrder.Default, arrayIterator)) - .hasNext()); - assertFalse(arrayIterator.hasNext()); - } - - @Test - public void testSortedDocumentIteratorConstructor2() { - Pair pair = new Pair(); - Pair pair1 = new Pair(); - ArrayIterator> arrayIterator = new ArrayIterator>( - new Pair[]{pair, pair1, new Pair()}); - assertFalse((new SortedDocumentCursor.SortedDocumentIterator("field", SortOrder.Ascending, null, NullOrder.Default, - arrayIterator)).hasNext()); - assertFalse(arrayIterator.hasNext()); - } - - @Test - public void testSortedDocumentIteratorConstructor3() { - Pair pair = new Pair(); - Pair pair1 = new Pair(); - ArrayIterator> arrayIterator = new ArrayIterator>( - new Pair[]{pair, pair1, new Pair()}); - assertFalse((new SortedDocumentCursor.SortedDocumentIterator("field", SortOrder.Ascending, null, NullOrder.First, - arrayIterator)).hasNext()); - assertFalse(arrayIterator.hasNext()); - } - - @Test - public void testSortedDocumentIteratorConstructor4() { - Pair pair = new Pair(); - Pair pair1 = new Pair(); - ArrayIterator> arrayIterator = new ArrayIterator>( - new Pair[]{pair, pair1, new Pair()}); - assertFalse((new SortedDocumentCursor.SortedDocumentIterator("field", null, null, NullOrder.First, arrayIterator)) - .hasNext()); - assertFalse(arrayIterator.hasNext()); - } - - @Test - public void testSortedDocumentIteratorConstructor5() { - Pair pair = new Pair(); - Pair pair1 = new Pair(); - ArrayIterator> arrayIterator = new ArrayIterator>( - new Pair[]{pair, pair1, new Pair()}); - assertFalse( - (new SortedDocumentCursor.SortedDocumentIterator("field", SortOrder.Ascending, null, null, arrayIterator)) - .hasNext()); - assertFalse(arrayIterator.hasNext()); - } - - @Test - public void testSortedDocumentIteratorConstructor6() { - assertFalse((new SortedDocumentCursor.SortedDocumentIterator("field", SortOrder.Ascending, null, NullOrder.First, - new ArrayIterator>(new Pair[]{}))).hasNext()); - } - - @Test - public void testSortedDocumentIteratorConstructor7() { - Pair pair = new Pair(); - Pair pair1 = new Pair(); - ArrayIterator> arrayIterator = new ArrayIterator>( - new Pair[]{pair, pair1, new Pair()}); - assertFalse((new SortedDocumentCursor.SortedDocumentIterator("field", null, null, NullOrder.Last, arrayIterator)) - .hasNext()); - assertFalse(arrayIterator.hasNext()); - } - - @Test - public void testSortedDocumentIteratorHasNext() { - Pair pair = new Pair(); - Pair pair1 = new Pair(); - assertFalse((new SortedDocumentCursor.SortedDocumentIterator("field", SortOrder.Ascending, null, NullOrder.First, - new ArrayIterator>(new Pair[]{pair, pair1, new Pair()}))) - .hasNext()); - } - - @Test - public void testSortedDocumentIteratorNext() { - NitriteId first = NitriteId.newId(); - Pair pair = new Pair(first, Document.createDocument()); - Pair pair1 = new Pair(); - assertSame(pair, - (new SortedDocumentCursor.SortedDocumentIterator("field", SortOrder.Ascending, null, NullOrder.First, - new ArrayIterator>(new Pair[]{pair, pair1, new Pair()}))) - .next()); - } -} - diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/operation/UnionStreamIteratorTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/operation/UnionStreamIteratorTest.java deleted file mode 100644 index bfd69e99b..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/operation/UnionStreamIteratorTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.dizitart.no2.collection.operation; - -import static org.junit.Assert.assertFalse; - -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.filters.Filter; -import org.junit.Test; - -public class UnionStreamIteratorTest { - @Test - public void testHasNext() { - FilteredRecordStream recordStream = new FilteredRecordStream(null, null); - FilteredRecordStream recordStream1 = new FilteredRecordStream(recordStream, Filter.byId(NitriteId.newId())); - FilteredRecordStream lhsStream = new FilteredRecordStream(recordStream1, Filter.byId(NitriteId.newId())); - FilteredRecordStream recordStream2 = new FilteredRecordStream(null, null); - FilteredRecordStream recordStream3 = new FilteredRecordStream(recordStream2, Filter.byId(NitriteId.newId())); - assertFalse( - (new UnionStreamIterator(lhsStream, new FilteredRecordStream(recordStream3, Filter.byId(NitriteId.newId())))) - .hasNext()); - } -} - diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/operation/WriteOperationsTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/operation/WriteOperationsTest.java deleted file mode 100644 index 26ab0f65c..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/collection/operation/WriteOperationsTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.dizitart.no2.collection.operation; - -import static org.junit.Assert.assertTrue; - -import org.dizitart.no2.NitriteConfig; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.collection.UpdateOptions; -import org.dizitart.no2.store.memory.InMemoryMap; -import org.junit.Test; - -public class WriteOperationsTest { - @Test - public void testUpdate() { - InMemoryMap nitriteMap = new InMemoryMap("mapName", null); - ReadOperations readOperations = new ReadOperations("collectionName", new NitriteConfig(), nitriteMap, null); - WriteOperations writeOperations = new WriteOperations(null, readOperations, - new InMemoryMap("mapName", null), null); - UpdateOptions updateOptions = UpdateOptions.updateOptions(true); - assertTrue(writeOperations.update(null, Document.createDocument(), updateOptions) instanceof WriteResultImpl); - } - - @Test - public void testRemove() { - InMemoryMap nitriteMap = new InMemoryMap("mapName", null); - ReadOperations readOperations = new ReadOperations("collectionName", new NitriteConfig(), nitriteMap, null); - assertTrue((new WriteOperations(null, readOperations, new InMemoryMap("mapName", null), null)) - .remove(null, true) instanceof WriteResultImpl); - } -} - diff --git a/nitrite/src/test/java/org/dizitart/no2/collection/operation/WriteResultImplTest.java b/nitrite/src/test/java/org/dizitart/no2/collection/operation/WriteResultImplTest.java index e1479fb89..aded72221 100644 --- a/nitrite/src/test/java/org/dizitart/no2/collection/operation/WriteResultImplTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/collection/operation/WriteResultImplTest.java @@ -1,17 +1,17 @@ package org.dizitart.no2.collection.operation; -import static org.junit.Assert.assertEquals; +import org.dizitart.no2.collection.NitriteId; +import org.junit.Test; import java.util.HashSet; -import org.dizitart.no2.collection.NitriteId; -import org.junit.Test; +import static org.junit.Assert.assertEquals; public class WriteResultImplTest { @Test public void testSetNitriteIds() { WriteResultImpl writeResultImpl = new WriteResultImpl(); - writeResultImpl.setNitriteIds(new HashSet()); + writeResultImpl.setNitriteIds(new HashSet<>()); assertEquals("WriteResultImpl(nitriteIds=[])", writeResultImpl.toString()); } @@ -25,7 +25,7 @@ public void testAddToList() { @Test public void testAddToList2() { WriteResultImpl writeResultImpl = new WriteResultImpl(); - writeResultImpl.setNitriteIds(new HashSet()); + writeResultImpl.setNitriteIds(new HashSet<>()); writeResultImpl.addToList(NitriteId.newId()); assertEquals(1, writeResultImpl.getAffectedCount()); } diff --git a/nitrite/src/test/java/org/dizitart/no2/common/FieldValuesTest.java b/nitrite/src/test/java/org/dizitart/no2/common/FieldValuesTest.java new file mode 100644 index 000000000..96c42cfbb --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/FieldValuesTest.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common; + +import org.dizitart.no2.common.tuples.Pair; +import org.junit.Test; + +import java.util.ArrayList; + +import static org.junit.Assert.*; + +public class FieldValuesTest { + @Test + public void testConstructor() { + assertEquals("FieldValues(nitriteId=null, fields=[], values=[])", (new FieldValues()).toString()); + } + + @Test + public void testGet() { + FieldValues fieldValues = new FieldValues(); + fieldValues.setFields(new Fields()); + assertNull(fieldValues.get("Field")); + } + + @Test + public void testGet2() { + Fields fields = new Fields(); + fields.addField("Field"); + + FieldValues fieldValues = new FieldValues(); + fieldValues.setFields(fields); + assertNull(fieldValues.get("Field")); + } + + @Test + public void testGetFields() { + FieldValues fieldValues = new FieldValues(); + assertEquals("[]", fieldValues.getFields().toString()); + assertEquals("FieldValues(nitriteId=null, fields=[], values=[])", fieldValues.toString()); + } + + @Test + public void testGetFields2() { + FieldValues fieldValues = new FieldValues(); + Fields fields = new Fields(); + fieldValues.setFields(fields); + assertSame(fields, fieldValues.getFields()); + } + + @Test + public void testGetFields3() { + ArrayList> pairList = new ArrayList<>(); + pairList.add(new Pair<>()); + + FieldValues fieldValues = new FieldValues(); + fieldValues.setValues(pairList); + fieldValues.getFields(); + assertEquals("FieldValues(nitriteId=null, fields=[], values=[Pair(first=null, second=null)])", + fieldValues.toString()); + } + + @Test + public void testGetFields4() { + ArrayList> pairList = new ArrayList<>(); + pairList.add(Pair.pair("First", "Second")); + + FieldValues fieldValues = new FieldValues(); + fieldValues.setValues(pairList); + fieldValues.getFields(); + assertEquals("FieldValues(nitriteId=null, fields=[First], values=[Pair(first=First, second=Second)])", + fieldValues.toString()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/FieldsTest.java b/nitrite/src/test/java/org/dizitart/no2/common/FieldsTest.java new file mode 100644 index 000000000..34887c467 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/FieldsTest.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common; + +import org.junit.Test; + +import java.util.List; + +import static org.junit.Assert.*; + +public class FieldsTest { + @Test + public void testConstructor() { + assertEquals("[]", (new Fields()).toString()); + } + + @Test + public void testWithNames() { + Fields actualWithNamesResult = Fields.withNames("Fields"); + assertEquals("[Fields]", actualWithNamesResult.toString()); + List stringList = actualWithNamesResult.fieldNames; + assertEquals(1, stringList.size()); + assertEquals("Fields", stringList.get(0)); + } + + @Test + public void testAddField() { + Fields fields = new Fields(); + assertSame(fields, fields.addField("Field")); + } + + @Test + public void testGetFieldNames() { + assertTrue((new Fields()).getFieldNames().isEmpty()); + } + + @Test + public void testStartsWith() { + Fields fields = new Fields(); + assertTrue(fields.startsWith(new Fields())); + } + + @Test + public void testStartsWith2() { + assertFalse((new Fields()).startsWith(null)); + } + + @Test + public void testStartsWith3() { + Fields fields = new Fields(); + assertFalse(fields.startsWith(Fields.withNames("foo", "foo", "foo"))); + } + + @Test + public void testGetEncodedName() { + assertEquals("", (new Fields()).getEncodedName()); + } + + @Test + public void testCompareTo() { + Fields fields = new Fields(); + assertEquals(0, fields.compareTo(new Fields())); + } + + @Test + public void testCompareTo2() { + Fields withNamesResult = Fields.withNames("foo", "foo", "foo"); + assertEquals(1, withNamesResult.compareTo(new Fields())); + } + + @Test + public void testCompareTo3() { + assertEquals(1, (new Fields()).compareTo(null)); + } + + @Test + public void testCompareTo4() { + Fields fields = new Fields(); + fields.setFieldNames(null); + assertEquals(1, fields.compareTo(null)); + } + + @Test + public void testCompareTo5() { + Fields withNamesResult = Fields.withNames("foo", "foo", "foo"); + assertEquals(0, withNamesResult.compareTo(Fields.withNames("foo", "foo", "foo"))); + } + + @Test + public void testCompareTo6() { + Fields withNamesResult = Fields.withNames("Fields", "foo", "foo"); + assertEquals(-32, withNamesResult.compareTo(Fields.withNames("foo", "foo", "foo"))); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/LookupTest.java b/nitrite/src/test/java/org/dizitart/no2/common/LookupTest.java new file mode 100644 index 000000000..e290fc9f1 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/LookupTest.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class LookupTest { + @Test + public void testCanEqual() { + assertFalse((new Lookup()).canEqual("Other")); + } + + @Test + public void testCanEqual2() { + Lookup lookup = new Lookup(); + assertTrue(lookup.canEqual(new Lookup())); + } + + @Test + public void testConstructor() { + Lookup actualLookup = new Lookup(); + actualLookup.setForeignField("Foreign Field"); + actualLookup.setLocalField("Local Field"); + actualLookup.setTargetField("Target Field"); + assertEquals("Foreign Field", actualLookup.getForeignField()); + assertEquals("Local Field", actualLookup.getLocalField()); + assertEquals("Target Field", actualLookup.getTargetField()); + } + + @Test + public void testEquals() { + assertFalse((new Lookup()).equals("42")); + } + + @Test + public void testEquals10() { + Lookup lookup = new Lookup(); + lookup.setLocalField("Local Field"); + + Lookup lookup1 = new Lookup(); + lookup1.setLocalField("Local Field"); + assertTrue(lookup.equals(lookup1)); + } + + @Test + public void testEquals11() { + Lookup lookup = new Lookup(); + lookup.setTargetField("Target Field"); + + Lookup lookup1 = new Lookup(); + lookup1.setTargetField("Target Field"); + assertTrue(lookup.equals(lookup1)); + } + + @Test + public void testEquals2() { + Lookup lookup = new Lookup(); + assertTrue(lookup.equals(new Lookup())); + } + + @Test + public void testEquals3() { + Lookup lookup = new Lookup(); + lookup.setForeignField("Foreign Field"); + assertFalse(lookup.equals(new Lookup())); + } + + @Test + public void testEquals4() { + Lookup lookup = new Lookup(); + lookup.setLocalField("Local Field"); + assertFalse(lookup.equals(new Lookup())); + } + + @Test + public void testEquals5() { + Lookup lookup = new Lookup(); + lookup.setTargetField("Target Field"); + assertFalse(lookup.equals(new Lookup())); + } + + @Test + public void testEquals6() { + Lookup lookup = new Lookup(); + + Lookup lookup1 = new Lookup(); + lookup1.setForeignField("Foreign Field"); + assertFalse(lookup.equals(lookup1)); + } + + @Test + public void testEquals7() { + Lookup lookup = new Lookup(); + + Lookup lookup1 = new Lookup(); + lookup1.setLocalField("Local Field"); + assertFalse(lookup.equals(lookup1)); + } + + @Test + public void testEquals8() { + Lookup lookup = new Lookup(); + + Lookup lookup1 = new Lookup(); + lookup1.setTargetField("Target Field"); + assertFalse(lookup.equals(lookup1)); + } + + @Test + public void testEquals9() { + Lookup lookup = new Lookup(); + lookup.setForeignField("Foreign Field"); + + Lookup lookup1 = new Lookup(); + lookup1.setForeignField("Foreign Field"); + assertTrue(lookup.equals(lookup1)); + } + + @Test + public void testHashCode() { + assertEquals(357642, (new Lookup()).hashCode()); + } + + @Test + public void testHashCode2() { + Lookup lookup = new Lookup(); + lookup.setForeignField("Foreign Field"); + assertEquals(1964140155, lookup.hashCode()); + } + + @Test + public void testHashCode3() { + Lookup lookup = new Lookup(); + lookup.setLocalField("Local Field"); + assertEquals(1343314452, lookup.hashCode()); + } + + @Test + public void testHashCode4() { + Lookup lookup = new Lookup(); + lookup.setTargetField("Target Field"); + assertEquals(-1878733174, lookup.hashCode()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/RecordStreamTest.java b/nitrite/src/test/java/org/dizitart/no2/common/RecordStreamTest.java new file mode 100644 index 000000000..604854e0e --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/RecordStreamTest.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class RecordStreamTest { + @Test + public void testEmpty() { + assertTrue(RecordStream.empty().toList().isEmpty()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/SortOrderTest.java b/nitrite/src/test/java/org/dizitart/no2/common/SortOrderTest.java new file mode 100644 index 000000000..ce59d4e21 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/SortOrderTest.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class SortOrderTest { + + @Test + public void testValueOf() { + assertEquals(SortOrder.Ascending, SortOrder.valueOf("Ascending")); + } + + @Test + public void testValues() { + SortOrder[] actualValuesResult = SortOrder.values(); + assertEquals(2, actualValuesResult.length); + assertEquals(SortOrder.Ascending, actualValuesResult[0]); + assertEquals(SortOrder.Descending, actualValuesResult[1]); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/SortableFieldsTest.java b/nitrite/src/test/java/org/dizitart/no2/common/SortableFieldsTest.java new file mode 100644 index 000000000..8019c7775 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/SortableFieldsTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common; + +import org.junit.Test; + +import java.util.List; + +import static org.junit.Assert.*; + +public class SortableFieldsTest { + @Test + public void testConstructor() { + assertEquals("[]", (new SortableFields()).toString()); + } + + @Test + public void testWithNames() { + SortableFields actualWithNamesResult = SortableFields.withNames("Fields"); + assertEquals("[Fields]", actualWithNamesResult.toString()); + List stringList = actualWithNamesResult.fieldNames; + assertEquals(1, stringList.size()); + assertEquals("Fields", stringList.get(0)); + } + + @Test + public void testAddField() { + SortableFields sortableFields = new SortableFields(); + assertSame(sortableFields, sortableFields.addField("Field", SortOrder.Ascending)); + } + + @Test + public void testGetSortingOrders() { + assertTrue((new SortableFields()).getSortingOrders().isEmpty()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/UnknownTypeTest.java b/nitrite/src/test/java/org/dizitart/no2/common/UnknownTypeTest.java new file mode 100644 index 000000000..96f9edf8b --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/UnknownTypeTest.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class UnknownTypeTest { + @Test + public void testCompareTo() { + UnknownType unknownType = new UnknownType(); + assertEquals(0, unknownType.compareTo(new UnknownType())); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/concurrent/ThreadPoolManagerTest.java b/nitrite/src/test/java/org/dizitart/no2/common/concurrent/ThreadPoolManagerTest.java index bd02d15d4..b64c32385 100644 --- a/nitrite/src/test/java/org/dizitart/no2/common/concurrent/ThreadPoolManagerTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/common/concurrent/ThreadPoolManagerTest.java @@ -1,13 +1,14 @@ package org.dizitart.no2.common.concurrent; -import static org.junit.Assert.assertTrue; - import org.junit.Test; +import static org.junit.Assert.assertTrue; + public class ThreadPoolManagerTest { @Test public void testGetThreadPool() { assertTrue(ThreadPoolManager.getThreadPool(3, "threadName") instanceof java.util.concurrent.ThreadPoolExecutor); + assertTrue(ThreadPoolManager.getThreadPool(1, "foo") instanceof java.util.concurrent.ThreadPoolExecutor); } } diff --git a/nitrite/src/test/java/org/dizitart/no2/common/crypto/AESEncryptorTest.java b/nitrite/src/test/java/org/dizitart/no2/common/crypto/AESEncryptorTest.java new file mode 100644 index 000000000..854bff17b --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/crypto/AESEncryptorTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.crypto; + +import org.dizitart.no2.exceptions.NitriteSecurityException; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class AESEncryptorTest { + @Test + public void testEncryptDecrypt() throws Exception { + AESEncryptor aesEncryptor = new AESEncryptor("iloveyou"); + String encrypted = aesEncryptor.encrypt("iloveyou".getBytes("UTF-8")); + assertNotNull(encrypted); + + assertEquals("iloveyou", aesEncryptor.decrypt(encrypted)); + } + + @Test(expected = NitriteSecurityException.class) + public void testDecrypt2() { + (new AESEncryptor("iloveyou")).decrypt("bad base-64"); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/event/EventTest.java b/nitrite/src/test/java/org/dizitart/no2/common/event/EventTest.java index 763a2da3b..bf73a45bb 100644 --- a/nitrite/src/test/java/org/dizitart/no2/common/event/EventTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/common/event/EventTest.java @@ -18,10 +18,10 @@ import org.dizitart.no2.Nitrite; import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.Retry; +import org.dizitart.no2.integration.Retry; import org.dizitart.no2.collection.events.EventType; import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.data.Employee; +import org.dizitart.no2.integration.repository.data.Employee; import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -145,7 +145,7 @@ public void testDrop() { } @Test - public void testClose() { + public void testClose() throws Exception { if (employeeRepository.isOpen()) { employeeRepository.close(); } @@ -196,7 +196,7 @@ public void testSingleEventListener() { } @After - public void clear() { + public void clear() throws Exception { if (employeeRepository != null) { if (!employeeRepository.isDropped() && employeeRepository.isOpen()) { diff --git a/nitrite/src/test/java/org/dizitart/no2/common/mapper/Company.java b/nitrite/src/test/java/org/dizitart/no2/common/mapper/Company.java new file mode 100644 index 000000000..ad947db76 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/mapper/Company.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017-2020. Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.mapper; + +import lombok.Data; +import org.dizitart.no2.collection.Document; + +import java.io.Serializable; + +/** + * @author Anindya Chatterjee. + */ +@Data +public class Company implements Mappable { + private String name; + private Long id; + private CompanyId companyId; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("id", id) + .put("name", name) + .put("companyId", mapper.convert(companyId, Document.class)); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + id = document.get("id", Long.class); + companyId = document.get("companyId", CompanyId.class); + } + + @Data + public static class CompanyId implements Comparable, Serializable, Mappable { + private Long idValue; + + public CompanyId(long value) { + this.idValue = value; + } + + @Override + public int compareTo(CompanyId other) { + return idValue.compareTo(other.idValue); + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument().put("idValue", idValue); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + idValue = document.get("idValue", Long.class); + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/mapper/Department.java b/nitrite/src/test/java/org/dizitart/no2/common/mapper/Department.java similarity index 97% rename from nitrite/src/test/java/org/dizitart/no2/mapper/Department.java rename to nitrite/src/test/java/org/dizitart/no2/common/mapper/Department.java index 330c744b3..5d1a5eb59 100644 --- a/nitrite/src/test/java/org/dizitart/no2/mapper/Department.java +++ b/nitrite/src/test/java/org/dizitart/no2/common/mapper/Department.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.dizitart.no2.mapper; +package org.dizitart.no2.common.mapper; import lombok.Data; import lombok.ToString; diff --git a/nitrite/src/test/java/org/dizitart/no2/common/mapper/Employee.java b/nitrite/src/test/java/org/dizitart/no2/common/mapper/Employee.java new file mode 100644 index 000000000..057a0f0cb --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/mapper/Employee.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017-2020. Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.mapper; + +import lombok.Data; +import lombok.ToString; +import org.dizitart.no2.collection.Document; + +import java.util.Date; + +/** + * @author Anindya Chatterjee + */ +@Data +@ToString +public class Employee implements Mappable { + private String empId; + private String name; + private Date joiningDate; + private Employee boss; + + @Override + public Document write(NitriteMapper mapper) { + Document document = Document.createDocument("empId", getEmpId()) + .put("name", getName()) + .put("joiningDate", getJoiningDate()); + + if (getBoss() != null) { + document.put("boss", mapper.convert(getBoss(), Document.class)); + } + return document; + } + + @Override + public void read(NitriteMapper mapper, Document document) { + setEmpId(document.get("empId", String.class)); + setName(document.get("name", String.class)); + setJoiningDate(document.get("joiningDate", Date.class)); + + Document bossDoc = document.get("boss", Document.class); + if (bossDoc != null) { + Employee boss = mapper.convert(bossDoc, Employee.class); + setBoss(boss); + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/mapper/MappableDepartment.java b/nitrite/src/test/java/org/dizitart/no2/common/mapper/MappableDepartment.java similarity index 98% rename from nitrite/src/test/java/org/dizitart/no2/mapper/MappableDepartment.java rename to nitrite/src/test/java/org/dizitart/no2/common/mapper/MappableDepartment.java index a549e3c50..b61548d0f 100644 --- a/nitrite/src/test/java/org/dizitart/no2/mapper/MappableDepartment.java +++ b/nitrite/src/test/java/org/dizitart/no2/common/mapper/MappableDepartment.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.dizitart.no2.mapper; +package org.dizitart.no2.common.mapper; import lombok.Data; import lombok.ToString; diff --git a/nitrite/src/test/java/org/dizitart/no2/mapper/MappableEmployee.java b/nitrite/src/test/java/org/dizitart/no2/common/mapper/MappableEmployee.java similarity index 97% rename from nitrite/src/test/java/org/dizitart/no2/mapper/MappableEmployee.java rename to nitrite/src/test/java/org/dizitart/no2/common/mapper/MappableEmployee.java index c4660c991..a2d7f79a1 100644 --- a/nitrite/src/test/java/org/dizitart/no2/mapper/MappableEmployee.java +++ b/nitrite/src/test/java/org/dizitart/no2/common/mapper/MappableEmployee.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.dizitart.no2.mapper; +package org.dizitart.no2.common.mapper; import lombok.Data; import lombok.ToString; diff --git a/nitrite/src/test/java/org/dizitart/no2/mapper/MappableMapperTest.java b/nitrite/src/test/java/org/dizitart/no2/common/mapper/MappableMapperTest.java similarity index 93% rename from nitrite/src/test/java/org/dizitart/no2/mapper/MappableMapperTest.java rename to nitrite/src/test/java/org/dizitart/no2/common/mapper/MappableMapperTest.java index 07cbca574..1e64953db 100644 --- a/nitrite/src/test/java/org/dizitart/no2/mapper/MappableMapperTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/common/mapper/MappableMapperTest.java @@ -1,7 +1,7 @@ -package org.dizitart.no2.mapper; +package org.dizitart.no2.common.mapper; -import org.dizitart.no2.NitriteStressTest; -import org.dizitart.no2.NitriteTest; +import org.dizitart.no2.integration.NitriteStressTest; +import org.dizitart.no2.integration.NitriteTest; import org.dizitart.no2.collection.Document; import org.dizitart.no2.exceptions.ObjectMappingException; import org.junit.Test; @@ -11,7 +11,7 @@ public class MappableMapperTest { @Test public void testConvert() { - MappableMapper mappableMapper = new MappableMapper(null); + MappableMapper mappableMapper = new MappableMapper(Integer.class); assertEquals(0, ((Integer) mappableMapper.convert(0, Object.class)).intValue()); } @@ -36,7 +36,7 @@ public void testConvertFromDocument() { Class forNameResult = Object.class; Class forNameResult1 = Object.class; MappableMapper mappableMapper = new MappableMapper(forNameResult, forNameResult1, Object.class); - assertNull(mappableMapper.convertFromDocument(null, Object.class)); + assertNull(mappableMapper.convertFromDocument(null, Object.class)); } @Test diff --git a/nitrite/src/test/java/org/dizitart/no2/mapper/MapperTest.java b/nitrite/src/test/java/org/dizitart/no2/common/mapper/MapperTest.java similarity index 98% rename from nitrite/src/test/java/org/dizitart/no2/mapper/MapperTest.java rename to nitrite/src/test/java/org/dizitart/no2/common/mapper/MapperTest.java index cc8cff608..e8eb86a86 100644 --- a/nitrite/src/test/java/org/dizitart/no2/mapper/MapperTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/common/mapper/MapperTest.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package org.dizitart.no2.mapper; +package org.dizitart.no2.common.mapper; -import org.dizitart.no2.Retry; +import org.dizitart.no2.integration.Retry; import org.dizitart.no2.collection.Document; import org.junit.Rule; import org.junit.Test; diff --git a/nitrite/src/test/java/org/dizitart/no2/common/module/PluginManagerTest.java b/nitrite/src/test/java/org/dizitart/no2/common/module/PluginManagerTest.java new file mode 100644 index 000000000..591e93492 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/module/PluginManagerTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.module; + +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.store.NitriteStore; +import org.junit.Test; + +import java.util.HashSet; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class PluginManagerTest { + @Test + public void testConstructor() { + NitriteConfig nitriteConfig = new NitriteConfig(); + assertSame(nitriteConfig, (new PluginManager(nitriteConfig)).getNitriteConfig()); + } + + @Test + public void testLoadModule() { + PluginManager pluginManager = new PluginManager(new NitriteConfig()); + NitriteModule nitriteModule = mock(NitriteModule.class); + when(nitriteModule.plugins()).thenReturn(new HashSet<>()); + pluginManager.loadModule(nitriteModule); + verify(nitriteModule, times(2)).plugins(); + } + + @Test + public void testLoadModule2() { + PluginManager pluginManager = new PluginManager(new NitriteConfig()); + + HashSet nitritePluginSet = new HashSet<>(); + nitritePluginSet.add(mock(NitritePlugin.class)); + NitriteModule nitriteModule = mock(NitriteModule.class); + when(nitriteModule.plugins()).thenReturn(nitritePluginSet); + pluginManager.loadModule(nitriteModule); + verify(nitriteModule, times(2)).plugins(); + } + + @Test + public void testFindAndLoadPlugins() { + PluginManager pluginManager = new PluginManager(new NitriteConfig()); + pluginManager.findAndLoadPlugins(); + NitriteStore nitriteStore = pluginManager.getNitriteStore(); + assertTrue(nitriteStore instanceof org.dizitart.no2.store.memory.InMemoryStore); + assertEquals(3, pluginManager.getIndexerMap().size()); + assertTrue(pluginManager.getNitriteMapper() instanceof org.dizitart.no2.common.mapper.MappableMapper); + assertFalse(nitriteStore.isClosed()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/processors/ProcessorChainTest.java b/nitrite/src/test/java/org/dizitart/no2/common/processors/ProcessorChainTest.java new file mode 100644 index 000000000..fddf3c192 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/processors/ProcessorChainTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.processors; + +import org.junit.Test; + +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.mock; + +public class ProcessorChainTest { + @Test + public void testRemove() { + ProcessorChain processorChain = new ProcessorChain(); + processorChain.add(new ProcessorChain()); + processorChain.remove(mock(Processor.class)); + } + + @Test + public void testProcessBeforeWrite() { + assertNull((new ProcessorChain()).processBeforeWrite(null)); + } + + @Test + public void testProcessBeforeWrite2() { + ProcessorChain processorChain = new ProcessorChain(); + processorChain.add(new ProcessorChain()); + assertNull(processorChain.processBeforeWrite(null)); + } + + @Test + public void testProcessAfterRead() { + assertNull((new ProcessorChain()).processAfterRead(null)); + } + + @Test + public void testProcessAfterRead2() { + ProcessorChain processorChain = new ProcessorChain(); + processorChain.add(new ProcessorChain()); + assertNull(processorChain.processAfterRead(null)); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/streams/BoundedDocumentStreamTest.java b/nitrite/src/test/java/org/dizitart/no2/common/streams/BoundedDocumentStreamTest.java new file mode 100644 index 000000000..4aa3a7054 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/streams/BoundedDocumentStreamTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.streams; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.exceptions.ValidationException; +import org.junit.Test; + +import java.util.Iterator; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.mockito.Mockito.*; + +public class BoundedDocumentStreamTest { + @Test + public void testConstructor() { + new BoundedDocumentStream(1L, 1L, (RecordStream>) mock(RecordStream.class)); + } + + @Test + public void testConstructor2() { + assertThrows(ValidationException.class, + () -> new BoundedDocumentStream(-1L, 1L, (RecordStream>) mock(RecordStream.class))); + } + + @Test + public void testConstructor3() { + assertThrows(ValidationException.class, + () -> new BoundedDocumentStream(1L, -1L, (RecordStream>) mock(RecordStream.class))); + } + + @Test + public void testIterator() { + RecordStream> recordStream = () -> new Iterator>() { + int i = 0; + + @Override + public boolean hasNext() { + return i != 3; + } + + @Override + public Pair next() { + i++; + return Pair.pair(NitriteId.newId(), Document.createDocument("value", i)); + } + }; + + BoundedDocumentStream stream = new BoundedDocumentStream(2L, 1L, recordStream); + + for (Pair pair : stream) { + assertEquals(3, (int) pair.getSecond().get("value", Integer.class)); + } + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/streams/DistinctStreamTest.java b/nitrite/src/test/java/org/dizitart/no2/common/streams/DistinctStreamTest.java new file mode 100644 index 000000000..defa949da --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/streams/DistinctStreamTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.streams; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.tuples.Pair; +import org.junit.Test; + +import java.util.Iterator; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +public class DistinctStreamTest { + @Test + public void testConstructor() { + DistinctStream distinctStream = new DistinctStream(null); + assertFalse(distinctStream.iterator().hasNext()); + } + + @Test + public void testConstructor2() { + RecordStream> recordStream = () -> new Iterator>() { + int i = 0; + + // same id for all entries + final NitriteId id = NitriteId.newId(); + + @Override + public boolean hasNext() { + return i != 2; + } + + @Override + public Pair next() { + i++; + return Pair.pair(id, Document.createDocument("value", i)); + } + }; + + assertEquals(2, recordStream.size()); + + DistinctStream distinctStream = new DistinctStream(recordStream); + assertEquals(1, distinctStream.size()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/streams/DocumentSorterTest.java b/nitrite/src/test/java/org/dizitart/no2/common/streams/DocumentSorterTest.java new file mode 100644 index 000000000..976a5971b --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/streams/DocumentSorterTest.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.streams; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.tuples.Pair; +import org.junit.Test; + +import java.util.ArrayList; + +import static org.junit.Assert.assertEquals; + +public class DocumentSorterTest { + @Test + public void testCompare() { + DocumentSorter documentSorter = new DocumentSorter(null, new ArrayList<>()); + Pair pair1 = new Pair<>(); + assertEquals(0, documentSorter.compare(pair1, new Pair<>())); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/streams/DocumentStreamTest.java b/nitrite/src/test/java/org/dizitart/no2/common/streams/DocumentStreamTest.java new file mode 100644 index 000000000..1ebeba433 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/streams/DocumentStreamTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.streams; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.Lookup; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.common.processors.ProcessorChain; +import org.junit.Test; + +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; + +@SuppressWarnings("unchecked") +public class DocumentStreamTest { + @Test + public void testConstructor() { + RecordStream> recordStream = (RecordStream>) mock( + RecordStream.class); + assertNull((new DocumentStream(recordStream, new ProcessorChain())).getFindPlan()); + } + + @Test + public void testJoin() { + RecordStream> recordStream = (RecordStream>) mock( + RecordStream.class); + DocumentStream documentStream = new DocumentStream(recordStream, new ProcessorChain()); + RecordStream> recordStream1 = (RecordStream>) mock( + RecordStream.class); + DocumentStream foreignCursor = new DocumentStream(recordStream1, new ProcessorChain()); + assertTrue(documentStream.join(foreignCursor, new Lookup()) instanceof JoinedDocumentStream); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/streams/FilteredStreamTest.java b/nitrite/src/test/java/org/dizitart/no2/common/streams/FilteredStreamTest.java new file mode 100644 index 000000000..e61dbba61 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/streams/FilteredStreamTest.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.streams; + +import com.fasterxml.jackson.databind.util.ArrayIterator; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.filters.Filter; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.*; + +@SuppressWarnings("unchecked") +public class FilteredStreamTest { + + @Test + public void testIterator() { + RecordStream> recordStream = (RecordStream>) mock( + RecordStream.class); + Pair pair = new Pair<>(); + Pair pair1 = new Pair<>(); + when(recordStream.iterator()).thenReturn( + new ArrayIterator>(new Pair[]{pair, pair1, new Pair()})); + FilteredStream filteredStream = new FilteredStream(recordStream, mock(Filter.class)); + filteredStream.iterator(); + verify(recordStream).iterator(); + assertTrue(filteredStream.toList().isEmpty()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/streams/IndexedStreamTest.java b/nitrite/src/test/java/org/dizitart/no2/common/streams/IndexedStreamTest.java new file mode 100644 index 000000000..40a9667c7 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/streams/IndexedStreamTest.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.streams; + +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.store.memory.InMemoryMap; +import org.junit.Test; + +import java.util.HashSet; + +import static org.junit.Assert.assertTrue; + +public class IndexedStreamTest { + @Test + public void testConstructor() { + HashSet nitriteIds = new HashSet<>(); + assertTrue( + (new IndexedStream(nitriteIds, new InMemoryMap<>("Map Name", null))).toList().isEmpty()); + } + + @Test + public void testIterator() { + HashSet nitriteIds = new HashSet<>(); + IndexedStream indexedStream = new IndexedStream(nitriteIds, new InMemoryMap<>("Map Name", null)); + indexedStream.iterator(); + assertTrue(indexedStream.toList().isEmpty()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/streams/JoinedDocumentStreamTest.java b/nitrite/src/test/java/org/dizitart/no2/common/streams/JoinedDocumentStreamTest.java new file mode 100644 index 000000000..302947a71 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/streams/JoinedDocumentStreamTest.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.streams; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.Lookup; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.common.processors.ProcessorChain; +import org.junit.Test; + +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.mock; + +@SuppressWarnings("unchecked") +public class JoinedDocumentStreamTest { + @Test + public void testConstructor() { + RecordStream> recordStream = (RecordStream>) mock( + RecordStream.class); + RecordStream> recordStream1 = (RecordStream>) mock( + RecordStream.class); + DocumentStream documentStream = new DocumentStream(recordStream1, new ProcessorChain()); + Lookup lookup = new Lookup(); + new JoinedDocumentStream(recordStream, documentStream, lookup, new ProcessorChain()); + assertNull(documentStream.getFindPlan()); + assertNull(lookup.getForeignField()); + assertNull(lookup.getTargetField()); + assertNull(lookup.getLocalField()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/streams/ProjectedDocumentStreamTest.java b/nitrite/src/test/java/org/dizitart/no2/common/streams/ProjectedDocumentStreamTest.java new file mode 100644 index 000000000..b07e1c288 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/streams/ProjectedDocumentStreamTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.streams; + +import com.fasterxml.jackson.databind.util.ArrayIterator; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.common.processors.ProcessorChain; +import org.junit.Test; + +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.*; + +@SuppressWarnings("unchecked") +public class ProjectedDocumentStreamTest { + @Test + public void testConstructor() { + RecordStream> recordStream = (RecordStream>) mock( + RecordStream.class); + new ProjectedDocumentStream(recordStream, null, new ProcessorChain()); + assertNull(null); + } + + @Test + public void testIterator() { + RecordStream> recordStream = (RecordStream>) mock( + RecordStream.class); + Pair pair = new Pair<>(); + Pair pair1 = new Pair<>(); + when(recordStream.iterator()).thenReturn( + new ArrayIterator>(new Pair[]{pair, pair1, new Pair()})); + ProjectedDocumentStream projectedDocumentStream = new ProjectedDocumentStream(recordStream, null, + new ProcessorChain()); + projectedDocumentStream.iterator(); + verify(recordStream).iterator(); + assertTrue(projectedDocumentStream.toList().isEmpty()); + } + + @Test + public void testIterator2() { + RecordStream> recordStream = (RecordStream>) mock( + RecordStream.class); + when(recordStream.iterator()).thenReturn(new ArrayIterator>(new Pair[]{})); + ProjectedDocumentStream projectedDocumentStream = new ProjectedDocumentStream(recordStream, null, + new ProcessorChain()); + projectedDocumentStream.iterator(); + verify(recordStream).iterator(); + assertTrue(projectedDocumentStream.toList().isEmpty()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/streams/SortedDocumentStreamTest.java b/nitrite/src/test/java/org/dizitart/no2/common/streams/SortedDocumentStreamTest.java new file mode 100644 index 000000000..7156cd267 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/streams/SortedDocumentStreamTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.streams; + +import com.fasterxml.jackson.databind.util.ArrayIterator; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.common.tuples.Pair; +import org.junit.Test; + +import java.util.List; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +@SuppressWarnings("unchecked") +public class SortedDocumentStreamTest { + @Test + public void testConstructor() { + FindPlan findPlan = new FindPlan(); + new SortedDocumentStream(findPlan, (RecordStream>) mock(RecordStream.class)); + List> blockingSortOrder = findPlan.getBlockingSortOrder(); + assertTrue(blockingSortOrder instanceof java.util.ArrayList); + assertEquals("FindPlan(byIdFilter=null, indexScanFilter=null, collectionScanFilter=null, indexDescriptor=null," + + " indexScanOrder=null, blockingSortOrder=[], skip=null, limit=null, collator=null, subPlans=[])", findPlan.toString()); + assertTrue(blockingSortOrder.isEmpty()); + List subPlans = findPlan.getSubPlans(); + assertTrue(subPlans instanceof java.util.ArrayList); + assertNull(findPlan.getSkip()); + assertTrue(subPlans.isEmpty()); + assertNull(findPlan.getLimit()); + assertNull(findPlan.getIndexScanOrder()); + assertNull(findPlan.getIndexScanFilter()); + assertNull(findPlan.getIndexDescriptor()); + assertNull(findPlan.getCollectionScanFilter()); + assertNull(findPlan.getCollator()); + } + + @Test + public void testIterator() { + RecordStream> recordStream = (RecordStream>) mock( + RecordStream.class); + Pair pair = new Pair<>(); + Pair pair1 = new Pair<>(); + when(recordStream.iterator()).thenReturn( + new ArrayIterator>(new Pair[]{pair, pair1, new Pair()})); + SortedDocumentStream sortedDocumentStream = new SortedDocumentStream(new FindPlan(), recordStream); + sortedDocumentStream.iterator(); + verify(recordStream).iterator(); + assertTrue(sortedDocumentStream.toList().isEmpty()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/streams/UnionStreamTest.java b/nitrite/src/test/java/org/dizitart/no2/common/streams/UnionStreamTest.java new file mode 100644 index 000000000..4d6724e39 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/streams/UnionStreamTest.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.streams; + +import org.junit.Test; + +import java.util.ArrayList; + +import static org.junit.Assert.assertTrue; + +public class UnionStreamTest { + @Test + public void testConstructor() { + assertTrue((new UnionStream(new ArrayList<>())).toList().isEmpty()); + } + + @Test + public void testIterator() { + UnionStream unionStream = new UnionStream(new ArrayList<>()); + unionStream.iterator(); + assertTrue(unionStream.toList().isEmpty()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/util/Base64Test.java b/nitrite/src/test/java/org/dizitart/no2/common/util/Base64Test.java new file mode 100644 index 000000000..dc5eafd89 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/util/Base64Test.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.util; + +import org.junit.Test; + +import java.io.UnsupportedEncodingException; + +import static org.junit.Assert.*; + +public class Base64Test { + @Test + public void testDecode() throws UnsupportedEncodingException { + byte[] actualDecodeResult = Base64.decode("AAAAAAAA".getBytes("UTF-8"), 1); + assertEquals(6, actualDecodeResult.length); + assertEquals((byte) 0, actualDecodeResult[0]); + assertEquals((byte) 0, actualDecodeResult[1]); + assertEquals((byte) 0, actualDecodeResult[2]); + assertEquals((byte) 0, actualDecodeResult[3]); + assertEquals((byte) 0, actualDecodeResult[4]); + assertEquals((byte) 0, actualDecodeResult[5]); + } + + @Test + public void testDecode2() { + byte[] actualDecodeResult = Base64.decode(new byte[]{0, 'A', 'A', 'A', 'A', 'A', 'A', 'A'}, 1); + assertEquals(5, actualDecodeResult.length); + assertEquals((byte) 0, actualDecodeResult[0]); + assertEquals((byte) 0, actualDecodeResult[1]); + assertEquals((byte) 0, actualDecodeResult[2]); + assertEquals((byte) 0, actualDecodeResult[3]); + assertEquals((byte) 0, actualDecodeResult[4]); + } + + @Test + public void testDecode3() throws UnsupportedEncodingException { + byte[] actualDecodeResult = Base64.decode("AAAAAAAA".getBytes("UTF-8"), 2, 3, 1); + assertEquals(2, actualDecodeResult.length); + assertEquals((byte) 0, actualDecodeResult[0]); + assertEquals((byte) 0, actualDecodeResult[1]); + } + + @Test + public void testDecode4() { + assertThrows(IllegalArgumentException.class, + () -> Base64.decode(new byte[]{'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'}, 1, 1, 1)); + } + + @Test + public void testDecode5() { + byte[] actualDecodeResult = Base64.decode(new byte[]{'A', 'A', 0, 'A', 'A', 'A', 'A', 'A'}, 2, 3, 1); + assertEquals(1, actualDecodeResult.length); + assertEquals((byte) 0, actualDecodeResult[0]); + } + + @Test + public void testDecode7() { + assertThrows(NegativeArraySizeException.class, + () -> Base64.decode("AAAAAAAA".getBytes("UTF-8"), 2, Integer.MIN_VALUE, 1)); + } + + @Test + public void testDecoderConstructor() throws UnsupportedEncodingException { + assertEquals(24, (new Base64.Decoder(1, "AAAAAAAAAAAAAAAAAAAAAAAA".getBytes("UTF-8"))).output.length); + assertEquals(24, (new Base64.Decoder(8, "AAAAAAAAAAAAAAAAAAAAAAAA".getBytes("UTF-8"))).output.length); + } + + @Test + public void testEncodeToString() throws UnsupportedEncodingException { + assertEquals("QUFBQUFBQUE\n", Base64.encodeToString("AAAAAAAA".getBytes("UTF-8"), 1)); + assertEquals("", Base64.encodeToString(new byte[]{}, 1)); + assertEquals("QUFBQUFBQUFBQUFBQUFBQQ\n", Base64.encodeToString("AAAAAAAAAAAAAAAA".getBytes("UTF-8"), 1)); + assertEquals("QUFBQUFBQUE=\n", Base64.encodeToString("AAAAAAAA".getBytes("UTF-8"), 0)); + assertEquals("QUFBQUFBQUE=", Base64.encodeToString("AAAAAAAA".getBytes("UTF-8"), 2)); + assertEquals("QUFBQUFBQUE=\r\n", Base64.encodeToString("AAAAAAAA".getBytes("UTF-8"), 4)); + assertEquals("", Base64.encodeToString(new byte[]{}, 0)); + } + + @Test + public void testEncode() throws UnsupportedEncodingException { + assertEquals(12, Base64.encode("AAAAAAAA".getBytes("UTF-8"), 1).length); + assertEquals(0, Base64.encode(new byte[]{}, 1).length); + assertEquals(23, Base64.encode("AAAAAAAAAAAAAAAA".getBytes("UTF-8"), 1).length); + assertEquals(13, Base64.encode("AAAAAAAA".getBytes("UTF-8"), 0).length); + assertEquals(12, Base64.encode("AAAAAAAA".getBytes("UTF-8"), 2).length); + assertEquals(14, Base64.encode("AAAAAAAA".getBytes("UTF-8"), 4).length); + assertEquals(0, Base64.encode(new byte[]{}, 0).length); + assertEquals(0, Base64.encode(new byte[]{'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'}, 1, 0, 1).length); + } + + @Test + public void testEncode2() throws UnsupportedEncodingException { + byte[] actualEncodeResult = Base64.encode("AAAAAAAA".getBytes("UTF-8"), 2, 3, 1); + assertEquals(5, actualEncodeResult.length); + assertEquals('Q', actualEncodeResult[0]); + assertEquals('U', actualEncodeResult[1]); + assertEquals('F', actualEncodeResult[2]); + assertEquals('B', actualEncodeResult[3]); + assertEquals((byte) 10, actualEncodeResult[4]); + } + + @Test + public void testEncode4() throws UnsupportedEncodingException { + byte[] actualEncodeResult = Base64.encode("AAAAAAAA".getBytes("UTF-8"), 2, 1, 1); + assertEquals(3, actualEncodeResult.length); + assertEquals('Q', actualEncodeResult[0]); + assertEquals('Q', actualEncodeResult[1]); + assertEquals((byte) 10, actualEncodeResult[2]); + } + + @Test + public void testEncode5() throws UnsupportedEncodingException { + byte[] actualEncodeResult = Base64.encode("AAAAAAAA".getBytes("UTF-8"), 2, 2, 1); + assertEquals(4, actualEncodeResult.length); + assertEquals('Q', actualEncodeResult[0]); + assertEquals('U', actualEncodeResult[1]); + assertEquals('E', actualEncodeResult[2]); + assertEquals((byte) 10, actualEncodeResult[3]); + } + + @Test + public void testEncode6() throws UnsupportedEncodingException { + byte[] actualEncodeResult = Base64.encode("AAAAAAAA".getBytes("UTF-8"), 2, 1, 0); + assertEquals(5, actualEncodeResult.length); + assertEquals('Q', actualEncodeResult[0]); + assertEquals('Q', actualEncodeResult[1]); + assertEquals('=', actualEncodeResult[2]); + assertEquals('=', actualEncodeResult[3]); + assertEquals((byte) 10, actualEncodeResult[4]); + } + + @Test + public void testEncode8() throws UnsupportedEncodingException { + byte[] actualEncodeResult = Base64.encode("AAAAAAAA".getBytes("UTF-8"), 2, 3, 4); + assertEquals(6, actualEncodeResult.length); + assertEquals('Q', actualEncodeResult[0]); + assertEquals('U', actualEncodeResult[1]); + assertEquals('F', actualEncodeResult[2]); + assertEquals('B', actualEncodeResult[3]); + assertEquals((byte) 13, actualEncodeResult[4]); + assertEquals((byte) 10, actualEncodeResult[5]); + } + + @Test + public void testEncoderConstructor() throws UnsupportedEncodingException { + Base64.Encoder actualEncoder = new Base64.Encoder(1, "AAAAAAAAAAAAAAAAAAAAAAAA".getBytes("UTF-8")); + assertFalse(actualEncoder.do_cr); + assertEquals(0, actualEncoder.tailLen); + assertEquals(24, actualEncoder.output.length); + assertFalse(actualEncoder.do_padding); + assertTrue(actualEncoder.do_newline); + } + + @Test + public void testEncoderConstructor2() throws UnsupportedEncodingException { + Base64.Encoder actualEncoder = new Base64.Encoder(0, "AAAAAAAAAAAAAAAAAAAAAAAA".getBytes("UTF-8")); + assertFalse(actualEncoder.do_cr); + assertEquals(0, actualEncoder.tailLen); + assertEquals(24, actualEncoder.output.length); + assertTrue(actualEncoder.do_padding); + assertTrue(actualEncoder.do_newline); + } + + @Test + public void testEncoderConstructor3() throws UnsupportedEncodingException { + Base64.Encoder actualEncoder = new Base64.Encoder(2, "AAAAAAAAAAAAAAAAAAAAAAAA".getBytes("UTF-8")); + assertFalse(actualEncoder.do_cr); + assertEquals(0, actualEncoder.tailLen); + assertEquals(24, actualEncoder.output.length); + assertTrue(actualEncoder.do_padding); + assertFalse(actualEncoder.do_newline); + } + + @Test + public void testEncoderConstructor4() throws UnsupportedEncodingException { + Base64.Encoder actualEncoder = new Base64.Encoder(4, "AAAAAAAAAAAAAAAAAAAAAAAA".getBytes("UTF-8")); + assertTrue(actualEncoder.do_cr); + assertEquals(0, actualEncoder.tailLen); + assertEquals(24, actualEncoder.output.length); + assertTrue(actualEncoder.do_padding); + assertTrue(actualEncoder.do_newline); + } + + @Test + public void testEncoderConstructor5() throws UnsupportedEncodingException { + Base64.Encoder actualEncoder = new Base64.Encoder(8, "AAAAAAAAAAAAAAAAAAAAAAAA".getBytes("UTF-8")); + assertFalse(actualEncoder.do_cr); + assertEquals(0, actualEncoder.tailLen); + assertEquals(24, actualEncoder.output.length); + assertTrue(actualEncoder.do_padding); + assertTrue(actualEncoder.do_newline); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/util/CryptoUtilsTest.java b/nitrite/src/test/java/org/dizitart/no2/common/util/CryptoUtilsTest.java new file mode 100644 index 000000000..70548f8cc --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/util/CryptoUtilsTest.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.util; + +import org.junit.Test; + +import java.io.UnsupportedEncodingException; +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; + +import static org.junit.Assert.*; + +public class CryptoUtilsTest { + @Test + public void testGetRandomNonce() { + assertEquals(10, CryptoUtils.getRandomNonce(10).length); + assertThrows(NegativeArraySizeException.class, () -> CryptoUtils.getRandomNonce(-1)); + } + + @Test + public void testGetAESKeyFromPassword() + throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeySpecException { + char[] password = "AAAA".toCharArray(); + assertTrue(CryptoUtils.getAESKeyFromPassword(password, + "AAAAAAAA".getBytes("UTF-8")) instanceof javax.crypto.spec.SecretKeySpec); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/util/DocumentUtilsTest.java b/nitrite/src/test/java/org/dizitart/no2/common/util/DocumentUtilsTest.java index 679865239..8776519f7 100644 --- a/nitrite/src/test/java/org/dizitart/no2/common/util/DocumentUtilsTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/common/util/DocumentUtilsTest.java @@ -17,13 +17,13 @@ package org.dizitart.no2.common.util; import org.dizitart.no2.NitriteBuilderTest; -import org.dizitart.no2.Retry; import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.MappableMapper; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.filters.ComparableFilter; import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.filters.IndexAwareFilter; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.MappableMapper; -import org.dizitart.no2.mapper.NitriteMapper; +import org.dizitart.no2.integration.Retry; import org.junit.Rule; import org.junit.Test; @@ -31,10 +31,6 @@ import static org.dizitart.no2.common.Constants.DOC_REVISION; import static org.dizitart.no2.common.util.DocumentUtils.*; import static org.junit.Assert.*; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; public class DocumentUtilsTest { @@ -74,7 +70,7 @@ public void testCreateUniqueFilter() { doc.getId(); Filter filter = createUniqueFilter(doc); assertNotNull(filter); - assertTrue(filter instanceof IndexAwareFilter); + assertTrue(filter instanceof ComparableFilter); } @Test diff --git a/nitrite/src/test/java/org/dizitart/no2/common/util/IndexUtilsTest.java b/nitrite/src/test/java/org/dizitart/no2/common/util/IndexUtilsTest.java new file mode 100644 index 000000000..d3de97e68 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/util/IndexUtilsTest.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.util; + +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.index.IndexDescriptor; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class IndexUtilsTest { + @Test + public void testDeriveIndexMapName() { + assertEquals("$nitrite_index|Collection Name||Index Type", + IndexUtils.deriveIndexMapName(new IndexDescriptor("Index Type", new Fields(), "Collection Name"))); + } + + @Test + public void testDeriveIndexMapName2() { + IndexDescriptor indexDescriptor = new IndexDescriptor("Index Type", new Fields(), "Collection Name"); + indexDescriptor.setIndexFields(new Fields()); + assertEquals("$nitrite_index|Collection Name||Index Type", IndexUtils.deriveIndexMapName(indexDescriptor)); + } + + @Test + public void testDeriveIndexMetaMapName() { + assertEquals("$nitrite_index_meta|Collection Name", IndexUtils.deriveIndexMetaMapName("Collection Name")); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/util/IterablesTest.java b/nitrite/src/test/java/org/dizitart/no2/common/util/IterablesTest.java index 66bb9c01c..dbb5aae24 100644 --- a/nitrite/src/test/java/org/dizitart/no2/common/util/IterablesTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/common/util/IterablesTest.java @@ -16,7 +16,7 @@ package org.dizitart.no2.common.util; -import org.dizitart.no2.Retry; +import org.dizitart.no2.integration.Retry; import org.junit.Rule; import org.junit.Test; @@ -112,7 +112,7 @@ public void testArrayContains() { @Test public void testListOf() { assertEquals(1, Iterables.listOf("items").size()); - assertEquals(0, Iterables.listOf( null).size()); + assertEquals(1, Iterables.listOf((Object) null).size()); } @Test diff --git a/nitrite/src/test/java/org/dizitart/no2/common/util/NumbersTest.java b/nitrite/src/test/java/org/dizitart/no2/common/util/NumbersTest.java index 5b319ac7e..872ab873e 100644 --- a/nitrite/src/test/java/org/dizitart/no2/common/util/NumbersTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/common/util/NumbersTest.java @@ -16,7 +16,7 @@ package org.dizitart.no2.common.util; -import org.dizitart.no2.Retry; +import org.dizitart.no2.integration.Retry; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/nitrite/src/test/java/org/dizitart/no2/common/util/ObjectUtilsTest.java b/nitrite/src/test/java/org/dizitart/no2/common/util/ObjectUtilsTest.java index d18f483df..8a6fea0db 100644 --- a/nitrite/src/test/java/org/dizitart/no2/common/util/ObjectUtilsTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/common/util/ObjectUtilsTest.java @@ -28,8 +28,8 @@ import org.dizitart.no2.exceptions.ValidationException; import org.dizitart.no2.repository.annotations.Entity; import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.data.ChildClass; -import org.dizitart.no2.repository.data.Employee; +import org.dizitart.no2.integration.repository.data.ChildClass; +import org.dizitart.no2.integration.repository.data.Employee; import org.junit.Test; import java.io.Serializable; diff --git a/nitrite/src/test/java/org/dizitart/no2/common/util/SecureStringTest.java b/nitrite/src/test/java/org/dizitart/no2/common/util/SecureStringTest.java new file mode 100644 index 000000000..fca7eea8c --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/common/util/SecureStringTest.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.common.util; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +public class SecureStringTest { + @Test + public void testConstructor() { + assertThrows(ArrayIndexOutOfBoundsException.class, () -> new SecureString(1, 3, + new SecureString(new SecureString(new SecureString(new SecureString("")))))); + assertEquals(2, (new SecureString(1, 3, + new SecureString(new SecureString(new SecureString(new SecureString("foo")))))).length()); + assertEquals(2, (new SecureString(1, 3, "foo")).length()); + assertThrows(NegativeArraySizeException.class, () -> new SecureString(Integer.MIN_VALUE, 3, + new SecureString(new SecureString(new SecureString(new SecureString("")))))); + assertEquals(0, + (new SecureString(new SecureString(new SecureString(new SecureString(new SecureString("")))))) + .length()); + assertEquals(1, + (new SecureString(new SecureString(new SecureString(new SecureString(new SecureString(String.valueOf('A'))))))) + .length()); + assertEquals(0, (new SecureString("")).length()); + assertEquals(1, (new SecureString(String.valueOf('A'))).length()); + assertThrows(ArrayIndexOutOfBoundsException.class, () -> new SecureString(1, 3, + new SecureString(new SecureString(new SecureString(new SecureString("")))))); + assertThrows(ArrayIndexOutOfBoundsException.class, + () -> new SecureString(1, 3, new SecureString(new SecureString(new SecureString(Long.toString(1L)))))); + assertEquals(2, (new SecureString(1, 3, + new SecureString(new SecureString(new SecureString(new SecureString("foo")))))).length()); + assertEquals(2, (new SecureString(1, 3, "foo")).length()); + assertThrows(NegativeArraySizeException.class, () -> new SecureString(Integer.MIN_VALUE, 3, + new SecureString(new SecureString(new SecureString(new SecureString("")))))); + assertEquals(0, + (new SecureString(new SecureString(new SecureString(new SecureString(new SecureString("")))))) + .length()); + assertEquals(1, + (new SecureString(new SecureString(new SecureString(new SecureString(new SecureString(String.valueOf('A'))))))) + .length()); + assertEquals(0, (new SecureString("")).length()); + assertEquals(1, (new SecureString(String.valueOf('A'))).length()); + } + + @Test + public void testCharAt2() { + assertEquals('o', + (new SecureString(new SecureString(new SecureString(new SecureString("foo"))))).charAt(1)); + } + + @Test + public void testCharAt4() { + assertEquals('o', + (new SecureString(new SecureString(new SecureString(new SecureString("foo"))))).charAt(1)); + } + + @Test + public void testLength() { + assertEquals(0, (new SecureString(new SecureString(new SecureString(new SecureString(""))))).length()); + assertEquals(0, (new SecureString(new SecureString(new SecureString(new SecureString(""))))).length()); + } + + + @Test + public void testSubSequence2() { + assertEquals(2, + (new SecureString(new SecureString(new SecureString(new SecureString("foo"))))).subSequence(1, 3) + .length()); + } + + @Test + public void testSubSequence3() { + assertThrows(NegativeArraySizeException.class, + () -> (new SecureString(new SecureString(new SecureString(new SecureString(""))))) + .subSequence(Integer.MIN_VALUE, 3)); + } + + + @Test + public void testSubSequence5() { + assertEquals(2, + (new SecureString(new SecureString(new SecureString(new SecureString("foo"))))).subSequence(1, 3) + .length()); + } + + @Test + public void testSubSequence6() { + assertThrows(NegativeArraySizeException.class, + () -> (new SecureString(new SecureString(new SecureString(new SecureString(""))))) + .subSequence(Integer.MIN_VALUE, 3)); + } + + @Test + public void testAsString() { + assertEquals("", (new SecureString(new SecureString(new SecureString(new SecureString(""))))).asString()); + assertEquals("A", + (new SecureString(new SecureString(new SecureString(new SecureString(String.valueOf('A')))))).asString()); + assertEquals("", (new SecureString(new SecureString(new SecureString(new SecureString(""))))).asString()); + assertEquals("A", + (new SecureString(new SecureString(new SecureString(new SecureString(String.valueOf('A')))))).asString()); + } + + @Test + public void testToString() { + assertEquals("Secure:XXXXX", + (new SecureString(new SecureString(new SecureString(new SecureString(""))))).toString()); + assertEquals("Secure:XXXXX", + (new SecureString(new SecureString(new SecureString(new SecureString(""))))).toString()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/common/util/StringUtilsTest.java b/nitrite/src/test/java/org/dizitart/no2/common/util/StringUtilsTest.java index b923a8699..1279d8842 100644 --- a/nitrite/src/test/java/org/dizitart/no2/common/util/StringUtilsTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/common/util/StringUtilsTest.java @@ -16,7 +16,7 @@ package org.dizitart.no2.common.util; -import org.dizitart.no2.Retry; +import org.dizitart.no2.integration.Retry; import org.junit.Rule; import org.junit.Test; diff --git a/nitrite/src/test/java/org/dizitart/no2/common/util/ValidationUtilsTest.java b/nitrite/src/test/java/org/dizitart/no2/common/util/ValidationUtilsTest.java index f03b13237..cd7721924 100644 --- a/nitrite/src/test/java/org/dizitart/no2/common/util/ValidationUtilsTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/common/util/ValidationUtilsTest.java @@ -16,7 +16,7 @@ package org.dizitart.no2.common.util; -import org.dizitart.no2.Retry; +import org.dizitart.no2.integration.Retry; import org.dizitart.no2.exceptions.ValidationException; import org.junit.Rule; import org.junit.Test; diff --git a/nitrite/src/test/java/org/dizitart/no2/exceptions/NitriteSecurityExceptionTest.java b/nitrite/src/test/java/org/dizitart/no2/exceptions/NitriteSecurityExceptionTest.java new file mode 100644 index 000000000..f4bd0b9cf --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/exceptions/NitriteSecurityExceptionTest.java @@ -0,0 +1,20 @@ +package org.dizitart.no2.exceptions; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +public class NitriteSecurityExceptionTest { + @Test + public void testConstructor() { + NitriteSecurityException actualSecurityException = new NitriteSecurityException("An error occurred"); + assertEquals("org.dizitart.no2.exceptions.NitriteSecurityException: An error occurred", + actualSecurityException.toString()); + assertEquals("An error occurred", actualSecurityException.getLocalizedMessage()); + assertNull(actualSecurityException.getCause()); + assertEquals("An error occurred", actualSecurityException.getMessage()); + assertEquals(0, actualSecurityException.getSuppressed().length); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/exceptions/SecurityExceptionTest.java b/nitrite/src/test/java/org/dizitart/no2/exceptions/SecurityExceptionTest.java deleted file mode 100644 index 0ea04bcb7..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/exceptions/SecurityExceptionTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.dizitart.no2.exceptions; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import org.junit.Test; - -public class SecurityExceptionTest { - @Test - public void testConstructor() { - SecurityException actualSecurityException = new SecurityException("An error occurred"); - assertEquals("org.dizitart.no2.exceptions.SecurityException: An error occurred", - actualSecurityException.toString()); - assertEquals("An error occurred", actualSecurityException.getLocalizedMessage()); - assertNull(actualSecurityException.getCause()); - assertEquals("An error occurred", actualSecurityException.getMessage()); - assertEquals(0, actualSecurityException.getSuppressed().length); - } -} - diff --git a/nitrite/src/test/java/org/dizitart/no2/filters/AndFilterTest.java b/nitrite/src/test/java/org/dizitart/no2/filters/AndFilterTest.java new file mode 100644 index 000000000..15408f80c --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/filters/AndFilterTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.filters; + +import org.dizitart.no2.common.tuples.Pair; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.*; + +public class AndFilterTest { + @Test + public void testConstructor() { + assertFalse((new AndFilter(mock(Filter.class), mock(Filter.class), mock(Filter.class))).getObjectFilter()); + } + + @Test + public void testApply() { + Filter filter = mock(Filter.class); + when(filter.apply(any())).thenReturn(true); + Filter filter1 = mock(Filter.class); + when(filter1.apply(any())).thenReturn(true); + Filter filter2 = mock(Filter.class); + when(filter2.apply(any())).thenReturn(true); + AndFilter andFilter = new AndFilter(filter, filter1, filter2); + assertTrue(andFilter.apply(new Pair<>())); + verify(filter1).apply(any()); + verify(filter2).apply(any()); + verify(filter).apply(any()); + } + + @Test + public void testApply2() { + Filter filter = mock(Filter.class); + when(filter.apply(any())).thenReturn(false); + Filter filter1 = mock(Filter.class); + when(filter1.apply(any())).thenReturn(true); + Filter filter2 = mock(Filter.class); + when(filter2.apply(any())).thenReturn(true); + AndFilter andFilter = new AndFilter(filter, filter1, filter2); + assertFalse(andFilter.apply(new Pair<>())); + verify(filter).apply(any()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/filters/BetweenFilterTest.java b/nitrite/src/test/java/org/dizitart/no2/filters/BetweenFilterTest.java index 87f5f53b6..cc1aecc29 100644 --- a/nitrite/src/test/java/org/dizitart/no2/filters/BetweenFilterTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/filters/BetweenFilterTest.java @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.filters; import org.dizitart.no2.exceptions.ValidationException; @@ -6,43 +23,80 @@ import static org.junit.Assert.*; public class BetweenFilterTest { + @Test + public void testBoundConstructor() { + BetweenFilter.Bound actualBound = new BetweenFilter.Bound<>("Lower Bound", "Upper Bound"); + Object lowerBound = actualBound.getLowerBound(); + assertTrue(lowerBound instanceof String); + assertEquals( + "BetweenFilter.Bound(upperBound=Upper Bound, lowerBound=Lower Bound, upperInclusive=true, lowerInclusive" + + "=true)", + actualBound.toString()); + assertEquals("Lower Bound", lowerBound); + assertTrue(actualBound.isUpperInclusive()); + assertTrue(actualBound.isLowerInclusive()); + Object upperBound = actualBound.getUpperBound(); + assertTrue(upperBound instanceof String); + assertEquals("Upper Bound", upperBound); + } + + @Test + public void testBoundConstructor2() { + BetweenFilter.Bound actualBound = new BetweenFilter.Bound<>("Lower Bound", "Upper Bound", true); + Object lowerBound = actualBound.getLowerBound(); + assertTrue(lowerBound instanceof String); + assertEquals( + "BetweenFilter.Bound(upperBound=Upper Bound, lowerBound=Lower Bound, upperInclusive=true, lowerInclusive" + + "=true)", + actualBound.toString()); + assertEquals("Lower Bound", lowerBound); + assertTrue(actualBound.isUpperInclusive()); + assertTrue(actualBound.isLowerInclusive()); + Object upperBound = actualBound.getUpperBound(); + assertTrue(upperBound instanceof String); + assertEquals("Upper Bound", upperBound); + } + + @Test + public void testBoundConstructor3() { + BetweenFilter.Bound actualBound = new BetweenFilter.Bound<>("Lower Bound", "Upper Bound", true, true); + Object lowerBound = actualBound.getLowerBound(); + assertTrue(lowerBound instanceof String); + assertEquals( + "BetweenFilter.Bound(upperBound=Upper Bound, lowerBound=Lower Bound, upperInclusive=true, lowerInclusive" + + "=true)", + actualBound.toString()); + assertEquals("Lower Bound", lowerBound); + assertTrue(actualBound.isUpperInclusive()); + assertTrue(actualBound.isLowerInclusive()); + Object upperBound = actualBound.getUpperBound(); + assertTrue(upperBound instanceof String); + assertEquals("Upper Bound", upperBound); + } + @Test public void testConstructor() { - BetweenFilter actualBetweenFilter = new BetweenFilter("field", - new BetweenFilter.Bound<>("lowerBound", "upperBound")); - Filter lhs = actualBetweenFilter.getLhs(); - assertTrue(lhs instanceof LesserEqualFilter); - Filter rhs = actualBetweenFilter.getRhs(); - assertTrue(rhs instanceof GreaterEqualFilter); - Boolean actualOnIdField = ((LesserEqualFilter) lhs).getOnIdField(); + BetweenFilter actualBetweenFilter = new BetweenFilter<>("Field", + new BetweenFilter.Bound<>("Lower Bound", "Upper Bound")); + assertEquals("((Field <= Upper Bound) && (Field >= Lower Bound))", actualBetweenFilter.toString()); assertFalse(actualBetweenFilter.getObjectFilter()); - assertFalse(((GreaterEqualFilter) rhs).getIsFieldIndexed()); - assertFalse(((GreaterEqualFilter) rhs).getObjectFilter()); - assertFalse(actualOnIdField); - assertEquals("field", ((GreaterEqualFilter) rhs).getField()); - assertTrue(((GreaterEqualFilter) rhs).getComparable() instanceof String); - assertFalse(((GreaterEqualFilter) rhs).getOnIdField()); - assertFalse(((LesserEqualFilter) lhs).getIsFieldIndexed()); - assertFalse(((LesserEqualFilter) lhs).getObjectFilter()); - assertEquals("field", ((LesserEqualFilter) lhs).getField()); - assertTrue(((LesserEqualFilter) lhs).getComparable() instanceof String); } @Test public void testConstructor2() { assertThrows(ValidationException.class, - () -> new BetweenFilter("field", new BetweenFilter.Bound("lowerBound", null))); + () -> new BetweenFilter<>("Field", new BetweenFilter.Bound<>(null, "Upper Bound"))); } @Test public void testConstructor3() { - assertThrows(ValidationException.class, () -> new BetweenFilter("field", null)); + assertThrows(ValidationException.class, + () -> new BetweenFilter<>("Field", new BetweenFilter.Bound<>("Lower Bound", null))); } @Test public void testConstructor4() { - assertThrows(ValidationException.class, - () -> new BetweenFilter("field", new BetweenFilter.Bound(null, "upperBound"))); + assertThrows(ValidationException.class, () -> new BetweenFilter<>("Field", null)); } } diff --git a/nitrite/src/test/java/org/dizitart/no2/filters/ElementMatchFilterTest.java b/nitrite/src/test/java/org/dizitart/no2/filters/ElementMatchFilterTest.java new file mode 100644 index 000000000..ffcf6f039 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/filters/ElementMatchFilterTest.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.filters; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.mockito.Mockito.mock; + +public class ElementMatchFilterTest { + @Test + public void testConstructor() { + assertFalse((new ElementMatchFilter("Field", mock(Filter.class))).getObjectFilter()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/filters/EqualsFilterTest.java b/nitrite/src/test/java/org/dizitart/no2/filters/EqualsFilterTest.java index 75eabb727..e6603ac20 100644 --- a/nitrite/src/test/java/org/dizitart/no2/filters/EqualsFilterTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/filters/EqualsFilterTest.java @@ -3,85 +3,39 @@ import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.exceptions.InvalidIdException; -import org.dizitart.no2.index.NitriteTextIndexer; -import org.dizitart.no2.index.NonUniqueIndexer; -import org.dizitart.no2.store.memory.InMemoryMap; import org.junit.Test; import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; public class EqualsFilterTest { @Test - public void testFindIndexedIdSet() { - EqualsFilter equalsFilter = new EqualsFilter("field", "value"); - equalsFilter.setIndexer(new NitriteTextIndexer()); - equalsFilter.setIsFieldIndexed(null); - assertEquals(0, equalsFilter.findIndexedIdSet().size()); - } - - @Test - public void testFindIndexedIdSet2() { - EqualsFilter equalsFilter = new EqualsFilter("field", new NonUniqueIndexer()); - equalsFilter.setIsFieldIndexed(true); - assertThrows(FilterException.class, () -> equalsFilter.findIndexedIdSet()); - } - - @Test - public void testFindIndexedIdSet3() { - EqualsFilter equalsFilter = new EqualsFilter("field", "value"); - equalsFilter.setIsFieldIndexed(true); - assertThrows(FilterException.class, () -> equalsFilter.findIndexedIdSet()); - } - - @Test - public void testFindIndexedIdSet4() { - EqualsFilter equalsFilter = new EqualsFilter("field", "value"); - equalsFilter.setIsFieldIndexed(true); - equalsFilter.setIndexer(new NitriteTextIndexer()); - equalsFilter.setIsFieldIndexed(null); - assertEquals(0, equalsFilter.findIndexedIdSet().size()); + public void testConstructor() { + EqualsFilter actualEqualsFilter = new EqualsFilter("Field", "Value"); + assertEquals("(Field == Value)", actualEqualsFilter.toString()); + assertFalse(actualEqualsFilter.getObjectFilter()); + assertEquals("Field", actualEqualsFilter.getField()); } @Test - public void testFindIndexedIdSet5() { - EqualsFilter equalsFilter = new EqualsFilter("field", null); - equalsFilter.setIsFieldIndexed(true); - assertThrows(FilterException.class, () -> equalsFilter.findIndexedIdSet()); + public void testToString() { + EqualsFilter equalsFilter = new EqualsFilter("Field", "Value"); + assertEquals("(Field == Value)", equalsFilter.toString()); + assertEquals("(!((Field == Value)))", equalsFilter.not().toString()); } @Test - public void testFindIndexedIdSet6() { - assertEquals(0, (new EqualsFilter("field", "value")).findIndexedIdSet().size()); - } - - @Test - public void testFindIdSet() { - EqualsFilter equalsFilter = new EqualsFilter("field", "value"); - assertEquals(0, equalsFilter.findIdSet(new InMemoryMap("mapName", null)).size()); - } - - @Test(expected = InvalidIdException.class) - public void testFindIdSet2() { - EqualsFilter equalsFilter = new EqualsFilter("field", "value"); - equalsFilter.setOnIdField(true); - equalsFilter.findIdSet(new InMemoryMap<>("mapName", null)); - assertTrue(equalsFilter.getValue() instanceof String); - } - - @Test - public void testFindIdSet3() { - EqualsFilter equalsFilter = new EqualsFilter("field", 42); - equalsFilter.setOnIdField(true); - assertEquals(0, equalsFilter.findIdSet(new InMemoryMap("mapName", null)).size()); - assertTrue(equalsFilter.getValue() instanceof Integer); + public void testToString2() { + EqualsFilter equalsFilter = new EqualsFilter("Field", "Value"); + equalsFilter.setProcessed(true); + equalsFilter.setObjectFilter(true); + assertEquals("(Field == Value)", equalsFilter.toString()); } @Test public void testApply() { EqualsFilter equalsFilter = new EqualsFilter("field", "value"); - Pair pair = new Pair(); + Pair pair = new Pair<>(); pair.setSecond(Document.createDocument()); assertFalse(equalsFilter.apply(pair)); assertTrue(equalsFilter.getValue() instanceof String); @@ -91,33 +45,8 @@ public void testApply() { public void testApply2() { EqualsFilter equalsFilter = new EqualsFilter("field", "value"); NitriteId first = NitriteId.newId(); - assertFalse(equalsFilter.apply(new Pair(first, Document.createDocument()))); + assertFalse(equalsFilter.apply(new Pair<>(first, Document.createDocument()))); assertTrue(equalsFilter.getValue() instanceof String); } - - @Test - public void testSetIsFieldIndexed() { - EqualsFilter equalsFilter = new EqualsFilter("field", "value"); - equalsFilter.setIsFieldIndexed(true); - assertTrue(equalsFilter.getIsFieldIndexed()); - } - - @Test - public void testSetIsFieldIndexed2() { - EqualsFilter equalsFilter = new EqualsFilter("field", 42); - equalsFilter.setObjectFilter(true); - equalsFilter.setIndexer(null); - equalsFilter.setIsFieldIndexed(true); - assertTrue(equalsFilter.getIsFieldIndexed()); - } - - @Test - public void testSetIsFieldIndexed3() { - EqualsFilter equalsFilter = new EqualsFilter("field", 42); - equalsFilter.setIndexer(new NitriteTextIndexer()); - equalsFilter.setIsFieldIndexed(true); - assertTrue(equalsFilter.getValue() instanceof Integer); - assertTrue(equalsFilter.getIsFieldIndexed()); - } } diff --git a/nitrite/src/test/java/org/dizitart/no2/filters/FilterTest.java b/nitrite/src/test/java/org/dizitart/no2/filters/FilterTest.java new file mode 100644 index 000000000..49256af76 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/filters/FilterTest.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.filters; + +import org.dizitart.no2.collection.NitriteId; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class FilterTest { + @Test + public void testById() { + assertTrue(((EqualsFilter) Filter.byId(NitriteId.newId())).getValue() instanceof String); + assertFalse(((EqualsFilter) Filter.byId(NitriteId.newId())).getObjectFilter()); + assertEquals("_id", ((EqualsFilter) Filter.byId(NitriteId.newId())).getField()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/filters/FluentFilterTest.java b/nitrite/src/test/java/org/dizitart/no2/filters/FluentFilterTest.java index cc69af570..5c9851180 100644 --- a/nitrite/src/test/java/org/dizitart/no2/filters/FluentFilterTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/filters/FluentFilterTest.java @@ -1,45 +1,46 @@ package org.dizitart.no2.filters; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - import org.junit.Test; +import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; + public class FluentFilterTest { @Test public void testEq() { - assertFalse(((EqualsFilter) FluentFilter.where("field").eq("value")).getOnIdField()); - assertTrue(((EqualsFilter) FluentFilter.where("field").eq("value")).getValue() instanceof String); - assertFalse(((EqualsFilter) FluentFilter.where("field").eq("value")).getObjectFilter()); - assertFalse(((EqualsFilter) FluentFilter.where("field").eq("value")).getIsFieldIndexed()); - assertEquals("field", ((EqualsFilter) FluentFilter.where("field").eq("value")).getField()); + NitriteFilter actualEqResult = FluentFilter.where("Field").eq("Value"); + assertEquals("(Field == Value)", actualEqResult.toString()); + assertFalse(actualEqResult.getObjectFilter()); + assertEquals("Field", ((EqualsFilter) actualEqResult).getField()); } @Test public void testNotEq() { - assertFalse(((NotEqualsFilter) FluentFilter.where("field").notEq("value")).getOnIdField()); - assertTrue(((NotEqualsFilter) FluentFilter.where("field").notEq("value")).getValue() instanceof String); - assertFalse(((NotEqualsFilter) FluentFilter.where("field").notEq("value")).getObjectFilter()); - assertFalse(((NotEqualsFilter) FluentFilter.where("field").notEq("value")).getIsFieldIndexed()); - assertEquals("field", ((NotEqualsFilter) FluentFilter.where("field").notEq("value")).getField()); + NitriteFilter actualNotEqResult = FluentFilter.where("Field").notEq("Value"); + assertEquals("(Field != Value)", actualNotEqResult.toString()); + assertFalse(actualNotEqResult.getObjectFilter()); + assertEquals("Field", ((NotEqualsFilter) actualNotEqResult).getField()); } @Test public void testText() { - assertEquals("value", ((TextFilter) FluentFilter.where("field").text("value")).getStringValue()); - assertFalse(((TextFilter) FluentFilter.where("field").text("value")).getOnIdField()); - assertFalse(((TextFilter) FluentFilter.where("field").text("value")).getObjectFilter()); - assertFalse(((TextFilter) FluentFilter.where("field").text("value")).getIsFieldIndexed()); - assertEquals("field", ((TextFilter) FluentFilter.where("field").text("value")).getField()); + NitriteFilter actualTextResult = FluentFilter.where("Field").text("42"); + assertEquals("Field", ((TextFilter) actualTextResult).getField()); + assertFalse(actualTextResult.getObjectFilter()); + assertEquals("42", ((TextFilter) actualTextResult).getStringValue()); } @Test public void testRegex() { - assertEquals("field", ((RegexFilter) FluentFilter.where("field").regex("value")).getField()); - assertFalse(((RegexFilter) FluentFilter.where("field").regex("value")).getObjectFilter()); - assertEquals("FieldBasedFilter(field=field, value=value, processed=true)", - ((RegexFilter) FluentFilter.where("field").regex("value")).toString()); + NitriteFilter actualRegexResult = FluentFilter.where("Field").regex("42"); + assertEquals("(Field regex 42)", actualRegexResult.toString()); + assertEquals("Field", ((RegexFilter) actualRegexResult).getField()); + assertFalse(actualRegexResult.getObjectFilter()); + } + + @Test + public void testElemMatch() { + assertFalse(FluentFilter.where("Field").elemMatch(mock(Filter.class)).getObjectFilter()); } } diff --git a/nitrite/src/test/java/org/dizitart/no2/filters/IndexScanFilterTest.java b/nitrite/src/test/java/org/dizitart/no2/filters/IndexScanFilterTest.java new file mode 100644 index 000000000..b7679c2c5 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/filters/IndexScanFilterTest.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.filters; + +import org.junit.Test; + +import java.util.ArrayList; + +import static org.junit.Assert.assertEquals; + +public class IndexScanFilterTest { + @Test + public void testConstructor() { + assertEquals("IndexScanFilter(filters=[])", (new IndexScanFilter(new ArrayList<>())).toString()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/filters/NotEqualsFilterTest.java b/nitrite/src/test/java/org/dizitart/no2/filters/NotEqualsFilterTest.java index fbe0ec347..b1c8d0cb3 100644 --- a/nitrite/src/test/java/org/dizitart/no2/filters/NotEqualsFilterTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/filters/NotEqualsFilterTest.java @@ -3,79 +3,33 @@ import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.common.tuples.Pair; -import org.dizitart.no2.exceptions.FilterException; -import org.dizitart.no2.exceptions.InvalidIdException; -import org.dizitart.no2.index.NitriteTextIndexer; -import org.dizitart.no2.index.NonUniqueIndexer; -import org.dizitart.no2.store.memory.InMemoryMap; import org.junit.Test; import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; public class NotEqualsFilterTest { @Test - public void testFindIndexedIdSet() { - NotEqualsFilter notEqualsFilter = new NotEqualsFilter("field", null); - notEqualsFilter.setIsFieldIndexed(true); - assertThrows(FilterException.class, () -> notEqualsFilter.findIndexedIdSet()); + public void testConstructor() { + NotEqualsFilter actualNotEqualsFilter = new NotEqualsFilter("Field", "Value"); + assertEquals("(Field != Value)", actualNotEqualsFilter.toString()); + assertFalse(actualNotEqualsFilter.getObjectFilter()); + assertEquals("Field", actualNotEqualsFilter.getField()); } @Test - public void testFindIndexedIdSet2() { - assertEquals(0, (new NotEqualsFilter("field", "value")).findIndexedIdSet().size()); + public void testToString() { + NotEqualsFilter notEqualsFilter = new NotEqualsFilter("Field", "Value"); + assertEquals("(Field != Value)", notEqualsFilter.toString()); + assertEquals("(!((Field != Value)))", notEqualsFilter.not().toString()); } @Test - public void testFindIndexedIdSet3() { - NotEqualsFilter notEqualsFilter = new NotEqualsFilter("field", new NonUniqueIndexer()); - notEqualsFilter.setIsFieldIndexed(true); - assertThrows(FilterException.class, () -> notEqualsFilter.findIndexedIdSet()); - } - - @Test - public void testFindIndexedIdSet4() { - NotEqualsFilter notEqualsFilter = new NotEqualsFilter("field", "value"); - notEqualsFilter.setIsFieldIndexed(true); - assertThrows(FilterException.class, () -> notEqualsFilter.findIndexedIdSet()); - } - - @Test - public void testFindIndexedIdSet5() { - NotEqualsFilter notEqualsFilter = new NotEqualsFilter("field", "value"); - notEqualsFilter.setIndexer(new NitriteTextIndexer()); - notEqualsFilter.setIsFieldIndexed(null); - assertEquals(0, notEqualsFilter.findIndexedIdSet().size()); - } - - @Test - public void testFindIndexedIdSet6() { - NotEqualsFilter notEqualsFilter = new NotEqualsFilter("field", "value"); - notEqualsFilter.setIsFieldIndexed(true); - notEqualsFilter.setIndexer(new NitriteTextIndexer()); - notEqualsFilter.setIsFieldIndexed(null); - assertEquals(0, notEqualsFilter.findIndexedIdSet().size()); - } - - @Test - public void testFindIdSet() { - NotEqualsFilter notEqualsFilter = new NotEqualsFilter("field", "value"); - assertEquals(0, notEqualsFilter.findIdSet(new InMemoryMap("mapName", null)).size()); - } - - @Test - public void testFindIdSet2() { - NotEqualsFilter notEqualsFilter = new NotEqualsFilter("field", 42); - notEqualsFilter.setOnIdField(true); - assertEquals(0, notEqualsFilter.findIdSet(new InMemoryMap<>("mapName", null)).size()); - assertTrue(notEqualsFilter.getValue() instanceof Integer); - } - - @Test(expected = InvalidIdException.class) - public void testFindIdSet3() { - NotEqualsFilter notEqualsFilter = new NotEqualsFilter("field", "value"); - notEqualsFilter.setOnIdField(true); - notEqualsFilter.findIdSet(new InMemoryMap<>("mapName", null)); - assertTrue(notEqualsFilter.getValue() instanceof String); + public void testToString2() { + NotEqualsFilter notEqualsFilter = new NotEqualsFilter("Field", "Value"); + notEqualsFilter.setProcessed(true); + notEqualsFilter.setObjectFilter(true); + assertEquals("(Field != Value)", notEqualsFilter.toString()); } @Test @@ -94,38 +48,5 @@ public void testApply2() { assertTrue(notEqualsFilter.apply(pair)); assertTrue(notEqualsFilter.getValue() instanceof String); } - - @Test - public void testSetIsFieldIndexed() { - NotEqualsFilter notEqualsFilter = new NotEqualsFilter("field", 42); - notEqualsFilter.setIndexer(new NitriteTextIndexer()); - notEqualsFilter.setIsFieldIndexed(true); - assertTrue(notEqualsFilter.getValue() instanceof Integer); - assertTrue(notEqualsFilter.getIsFieldIndexed()); - } - - @Test - public void testSetIsFieldIndexed2() { - NotEqualsFilter notEqualsFilter = new NotEqualsFilter("field", 42); - notEqualsFilter.setObjectFilter(true); - notEqualsFilter.setIndexer(null); - notEqualsFilter.setIsFieldIndexed(true); - assertTrue(notEqualsFilter.getIsFieldIndexed()); - } - - @Test - public void testSetIsFieldIndexed3() { - NotEqualsFilter notEqualsFilter = new NotEqualsFilter("field", "value"); - notEqualsFilter.setIsFieldIndexed(true); - assertTrue(notEqualsFilter.getIsFieldIndexed()); - } - - @Test - public void testSetIsFieldIndexed4() { - NotEqualsFilter notEqualsFilter = new NotEqualsFilter("field", "value"); - notEqualsFilter.setIndexer(new NitriteTextIndexer()); - notEqualsFilter.setIsFieldIndexed(true); - assertTrue(notEqualsFilter.getValue() instanceof String); - } } diff --git a/nitrite/src/test/java/org/dizitart/no2/filters/NotFilterTest.java b/nitrite/src/test/java/org/dizitart/no2/filters/NotFilterTest.java new file mode 100644 index 000000000..6049fa700 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/filters/NotFilterTest.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.filters; + +import org.dizitart.no2.common.tuples.Pair; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.*; + +public class NotFilterTest { + @Test + public void testConstructor() { + assertFalse((new NotFilter(mock(Filter.class))).getObjectFilter()); + } + + @Test + public void testApply() { + Filter filter = mock(Filter.class); + when(filter.apply(any())).thenReturn(true); + NotFilter notFilter = new NotFilter(filter); + assertFalse(notFilter.apply(new Pair<>())); + verify(filter).apply(any()); + } + + @Test + public void testApply2() { + Filter filter = mock(Filter.class); + when(filter.apply(any())).thenReturn(false); + NotFilter notFilter = new NotFilter(filter); + assertTrue(notFilter.apply(new Pair<>())); + verify(filter).apply(any()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/filters/OrFilterTest.java b/nitrite/src/test/java/org/dizitart/no2/filters/OrFilterTest.java new file mode 100644 index 000000000..8316a6b7a --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/filters/OrFilterTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.filters; + +import org.dizitart.no2.common.tuples.Pair; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.*; + +public class OrFilterTest { + @Test + public void testConstructor() { + assertFalse((new OrFilter(mock(Filter.class), mock(Filter.class), mock(Filter.class))).getObjectFilter()); + } + + @Test + public void testApply() { + Filter filter = mock(Filter.class); + when(filter.apply(any())).thenReturn(true); + OrFilter orFilter = new OrFilter(filter, mock(Filter.class), mock(Filter.class)); + assertTrue(orFilter.apply(new Pair<>())); + verify(filter).apply(any()); + } + + @Test + public void testApply2() { + Filter filter = mock(Filter.class); + when(filter.apply(any())).thenReturn(false); + Filter filter1 = mock(Filter.class); + when(filter1.apply(any())).thenReturn(true); + OrFilter orFilter = new OrFilter(filter, filter1, mock(Filter.class)); + assertTrue(orFilter.apply(new Pair<>())); + verify(filter1).apply(any()); + verify(filter).apply(any()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/filters/RegexFilterTest.java b/nitrite/src/test/java/org/dizitart/no2/filters/RegexFilterTest.java index e93925522..d5a8d8f4f 100644 --- a/nitrite/src/test/java/org/dizitart/no2/filters/RegexFilterTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/filters/RegexFilterTest.java @@ -1,26 +1,41 @@ package org.dizitart.no2.filters; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - import org.dizitart.no2.collection.Document; import org.dizitart.no2.collection.NitriteId; import org.dizitart.no2.common.tuples.Pair; import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + public class RegexFilterTest { @Test public void testConstructor() { - RegexFilter actualRegexFilter = new RegexFilter("field", "value"); - assertEquals("field", actualRegexFilter.getField()); + RegexFilter actualRegexFilter = new RegexFilter("Field", "42"); + assertEquals("(Field regex 42)", actualRegexFilter.toString()); + assertEquals("Field", actualRegexFilter.getField()); assertFalse(actualRegexFilter.getObjectFilter()); - assertEquals("FieldBasedFilter(field=field, value=value, processed=true)", actualRegexFilter.toString()); + } + + @Test + public void testToString() { + RegexFilter regexFilter = new RegexFilter("Field", "42"); + assertEquals("(Field regex 42)", regexFilter.toString()); + assertEquals("(!((Field regex 42)))", regexFilter.not().toString()); + } + + @Test + public void testToString2() { + RegexFilter regexFilter = new RegexFilter("Field", "42"); + regexFilter.setProcessed(true); + regexFilter.setObjectFilter(true); + assertEquals("(Field regex 42)", regexFilter.toString()); } @Test public void testApply() { RegexFilter regexFilter = new RegexFilter("field", "value"); - Pair pair = new Pair(); + Pair pair = new Pair<>(); pair.setSecond(Document.createDocument()); assertFalse(regexFilter.apply(pair)); } @@ -29,7 +44,7 @@ public void testApply() { public void testApply2() { RegexFilter regexFilter = new RegexFilter("field", "value"); NitriteId first = NitriteId.newId(); - assertFalse(regexFilter.apply(new Pair(first, Document.createDocument()))); + assertFalse(regexFilter.apply(new Pair<>(first, Document.createDocument()))); } } diff --git a/nitrite/src/test/java/org/dizitart/no2/filters/TextFilterTest.java b/nitrite/src/test/java/org/dizitart/no2/filters/TextFilterTest.java index bc146b614..c942d0e33 100644 --- a/nitrite/src/test/java/org/dizitart/no2/filters/TextFilterTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/filters/TextFilterTest.java @@ -1,30 +1,67 @@ -package org.dizitart.no2.filters; +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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. + * + */ -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThrows; +package org.dizitart.no2.filters; import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.index.fulltext.EnglishTextTokenizer; +import org.dizitart.no2.store.memory.InMemoryMap; import org.junit.Test; +import static org.junit.Assert.*; + public class TextFilterTest { @Test - public void testFindIndexedIdSet() { - assertEquals(0, (new TextFilter("field", "value")).findIndexedIdSet().size()); + public void testConstructor() { + TextFilter actualTextFilter = new TextFilter("Field", "42"); + assertEquals("Field", actualTextFilter.getField()); + assertFalse(actualTextFilter.getObjectFilter()); + assertEquals("42", actualTextFilter.getStringValue()); + } + + @Test + public void testToString() { + TextFilter textFilter = new TextFilter("Field", "42"); + assertEquals("(Field like 42)", textFilter.toString()); + assertEquals("42", textFilter.getStringValue()); + } + + @Test + public void testToString2() { + TextFilter textFilter = new TextFilter("Field", "42"); + textFilter.setProcessed(true); + textFilter.setObjectFilter(true); + assertEquals("(Field like 42)", textFilter.toString()); } @Test - public void testFindIndexedIdSet2() { - TextFilter textFilter = new TextFilter("field", "value"); - textFilter.setIndexer(null); - textFilter.setIsFieldIndexed(true); - assertThrows(FilterException.class, () -> textFilter.findIndexedIdSet()); + public void testApplyOnIndex() { + TextFilter textFilter = new TextFilter("Field", "42"); + textFilter.setTextTokenizer(new EnglishTextTokenizer()); + assertTrue(textFilter.applyOnIndex(new InMemoryMap<>("Map Name", null)).isEmpty()); + assertEquals("42", textFilter.getStringValue()); } @Test - public void testFindIndexedIdSet3() { - TextFilter textFilter = new TextFilter("field", "value"); - textFilter.setIsFieldIndexed(true); - assertThrows(FilterException.class, () -> textFilter.findIndexedIdSet()); + public void testApplyOnIndex3() { + TextFilter textFilter = new TextFilter("Field", "*"); + textFilter.setTextTokenizer(new EnglishTextTokenizer()); + assertThrows(FilterException.class, + () -> textFilter.applyOnIndex(new InMemoryMap<>("Map Name", null))); } } diff --git a/nitrite/src/test/java/org/dizitart/no2/index/CompoundIndexTest.java b/nitrite/src/test/java/org/dizitart/no2/index/CompoundIndexTest.java new file mode 100644 index 000000000..2e07be283 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/index/CompoundIndexTest.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.index; + +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.common.FieldValues; +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.store.memory.InMemoryStore; +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class CompoundIndexTest { + @Test + public void testConstructor() { + IndexDescriptor indexDescriptor = new IndexDescriptor("Index Type", new Fields(), "Collection Name"); + assertSame(indexDescriptor, (new CompoundIndex(indexDescriptor, null)).getIndexDescriptor()); + } + + @Test + public void testWrite() { + CompoundIndex compoundIndex = new CompoundIndex(new IndexDescriptor("Index Type", Fields.withNames("a"), "Collection Name"), + new InMemoryStore()); + FieldValues fieldValues = new FieldValues(); + fieldValues.getValues().add(Pair.pair("a", 1)); + compoundIndex.write(fieldValues); + assertEquals("FieldValues(nitriteId=null, fields=[a], values=[Pair(first=a, second=1)])", fieldValues.toString()); + assertEquals("[a]", fieldValues.getFields().toString()); + } + + @Test + public void testRemove() { + CompoundIndex compoundIndex = new CompoundIndex(new IndexDescriptor("Index Type", Fields.withNames("a"), "Collection Name"), + new InMemoryStore()); + FieldValues fieldValues = new FieldValues(); + fieldValues.getValues().add(Pair.pair("a", 1)); + compoundIndex.remove(fieldValues); + assertEquals("FieldValues(nitriteId=null, fields=[a], values=[Pair(first=a, second=1)])", fieldValues.toString()); + assertEquals("[a]", fieldValues.getFields().toString()); + } + + @Test(expected = IndexingException.class) + public void testDrop() { + Fields fields = mock(Fields.class); + when(fields.getEncodedName()).thenThrow(new IndexingException("An error occurred")); + CompoundIndex compoundIndex = new CompoundIndex(new IndexDescriptor("Index Type", fields, "Collection Name"), + new InMemoryStore()); + compoundIndex.drop(); + verify(fields).getEncodedName(); + assertFalse(compoundIndex.getIndexDescriptor().isCompoundIndex()); + } + + @Test + public void testDrop2() { + Fields fields = mock(Fields.class); + when(fields.getEncodedName()).thenReturn("foo"); + IndexDescriptor indexDescriptor = new IndexDescriptor("Index Type", fields, "Collection Name"); + CompoundIndex compoundIndex = new CompoundIndex(indexDescriptor, new InMemoryStore()); + compoundIndex.drop(); + verify(fields).getEncodedName(); + assertFalse(compoundIndex.getIndexDescriptor().isCompoundIndex()); + } + + @Test + public void testFindNitriteIds() { + CompoundIndex compoundIndex = new CompoundIndex(new IndexDescriptor("Index Type", new Fields(), "Collection Name"), + null); + assertTrue(compoundIndex.findNitriteIds(new FindPlan()).isEmpty()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/index/IndexDescriptorTest.java b/nitrite/src/test/java/org/dizitart/no2/index/IndexDescriptorTest.java new file mode 100644 index 000000000..0b5cc9919 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/index/IndexDescriptorTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.index; + +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.exceptions.ValidationException; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class IndexDescriptorTest { + @Test + public void testConstructor() { + IndexDescriptor actualIndexDescriptor = new IndexDescriptor("Index Type", new Fields(), "Collection Name"); + assertEquals("Collection Name", actualIndexDescriptor.getCollectionName()); + assertFalse(actualIndexDescriptor.isCompoundIndex()); + assertEquals("Index Type", actualIndexDescriptor.getIndexType()); + } + + @Test(expected = ValidationException.class) + public void testConstructor3() { + Fields fields = new Fields(); + new IndexDescriptor("Index Type", fields, ""); + assertEquals("", fields.getEncodedName()); + assertEquals("[]", fields.toString()); + } + + @Test + public void testCompareTo() { + IndexDescriptor indexDescriptor = new IndexDescriptor("Index Type", new Fields(), "Collection Name"); + assertEquals(0, indexDescriptor.compareTo(new IndexDescriptor("Index Type", new Fields(), "Collection Name"))); + } + + @Test + public void testIsCompoundIndex() { + assertFalse((new IndexDescriptor("Index Type", new Fields(), "Collection Name")).isCompoundIndex()); + } + + @Test + public void testIsCompoundIndex2() { + Fields fields = new Fields(); + fields.addField("Field"); + fields.addField("Field"); + assertTrue((new IndexDescriptor("Index Type", fields, "Collection Name")).isCompoundIndex()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/index/IndexEntryTest.java b/nitrite/src/test/java/org/dizitart/no2/index/IndexEntryTest.java deleted file mode 100644 index da403c815..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/index/IndexEntryTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.dizitart.no2.index; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -public class IndexEntryTest { - @Test - public void testConstructor() { - IndexEntry actualIndexEntry = new IndexEntry("indexType", "field", "collectionName"); - assertEquals("indexType", actualIndexEntry.getIndexType()); - assertEquals("collectionName", actualIndexEntry.getCollectionName()); - assertEquals("field", actualIndexEntry.getField()); - } - - @Test - public void testCompareTo() { - IndexEntry indexEntry = new IndexEntry("", "", "collectionName"); - assertEquals(-14, indexEntry.compareTo(new IndexEntry("indexType", "field", "collectionName"))); - } - - @Test - public void testCompareTo2() { - IndexEntry indexEntry = new IndexEntry("indexType", "field", "collectionName"); - assertEquals(0, indexEntry.compareTo(new IndexEntry("indexType", "field", "collectionName"))); - } -} - diff --git a/nitrite/src/test/java/org/dizitart/no2/index/IndexMapTest.java b/nitrite/src/test/java/org/dizitart/no2/index/IndexMapTest.java new file mode 100644 index 000000000..647b16da4 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/index/IndexMapTest.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.index; + +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.store.memory.InMemoryMap; +import org.junit.Test; + +import java.util.List; +import java.util.TreeMap; +import java.util.concurrent.CopyOnWriteArrayList; + +import static org.junit.Assert.*; + +public class IndexMapTest { + @Test + public void testConstructor() { + TreeMap dbValueObjectMap = new TreeMap<>(); + IndexMap actualIndexMap = new IndexMap(dbValueObjectMap); + List terminalNitriteIds = actualIndexMap.getTerminalNitriteIds(); + assertTrue(terminalNitriteIds instanceof CopyOnWriteArrayList); + assertFalse(actualIndexMap.isReverseScan()); + assertTrue(terminalNitriteIds.isEmpty()); + assertTrue(dbValueObjectMap.isEmpty()); + } + + @Test + public void testConstructor2() { + InMemoryMap inMemoryMap = new InMemoryMap<>("Map Name", null); + IndexMap actualIndexMap = new IndexMap(inMemoryMap); + List terminalNitriteIds = actualIndexMap.getTerminalNitriteIds(); + assertTrue(terminalNitriteIds instanceof CopyOnWriteArrayList); + assertFalse(actualIndexMap.isReverseScan()); + assertTrue(terminalNitriteIds.isEmpty()); + assertEquals("Map Name", inMemoryMap.getName()); + assertEquals(0L, inMemoryMap.size()); + assertTrue(inMemoryMap.isEmpty()); + assertNull(inMemoryMap.getStore()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/index/IndexOptionsTest.java b/nitrite/src/test/java/org/dizitart/no2/index/IndexOptionsTest.java index 4f6dd5652..39b10ad38 100644 --- a/nitrite/src/test/java/org/dizitart/no2/index/IndexOptionsTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/index/IndexOptionsTest.java @@ -7,16 +7,7 @@ public class IndexOptionsTest { @Test public void testIndexOptions() { - IndexOptions actualIndexOptionsResult = IndexOptions.indexOptions("indexType", true); - assertTrue(actualIndexOptionsResult.isAsync()); - assertEquals("indexType", actualIndexOptionsResult.getIndexType()); - } - - @Test - public void testIndexOptions2() { - IndexOptions actualIndexOptionsResult = IndexOptions.indexOptions("indexType"); - assertFalse(actualIndexOptionsResult.isAsync()); - assertEquals("indexType", actualIndexOptionsResult.getIndexType()); + assertEquals("Index Type", IndexOptions.indexOptions("Index Type").getIndexType()); } } diff --git a/nitrite/src/test/java/org/dizitart/no2/index/NitriteTextIndexerTest.java b/nitrite/src/test/java/org/dizitart/no2/index/NitriteTextIndexerTest.java index c31207dfc..4ccfe6ca9 100644 --- a/nitrite/src/test/java/org/dizitart/no2/index/NitriteTextIndexerTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/index/NitriteTextIndexerTest.java @@ -1,12 +1,22 @@ package org.dizitart.no2.index; +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.common.FieldValues; +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.index.fulltext.EnglishTextTokenizer; +import org.dizitart.no2.store.memory.InMemoryStore; import org.junit.Test; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; public class NitriteTextIndexerTest { @Test public void testConstructor() { + assertEquals(IndexType.FULL_TEXT, (new NitriteTextIndexer(new EnglishTextTokenizer())).getIndexType()); assertEquals("Fulltext", (new NitriteTextIndexer()).getIndexType()); } @@ -14,5 +24,126 @@ public void testConstructor() { public void testGetIndexType() { assertEquals("Fulltext", (new NitriteTextIndexer()).getIndexType()); } + + @Test + public void testInitialize() { + NitriteTextIndexer nitriteTextIndexer = new NitriteTextIndexer(); + NitriteConfig nitriteConfig = new NitriteConfig(); + nitriteTextIndexer.initialize(nitriteConfig); + assertEquals(1, nitriteConfig.getSchemaVersion().intValue()); + } + + @Test + public void testValidateIndex() { + NitriteTextIndexer nitriteTextIndexer = new NitriteTextIndexer(); + Fields fields = new Fields(); + nitriteTextIndexer.validateIndex(fields); + assertEquals("[]", fields.toString()); + } + + @Test + public void testValidateIndex2() { + NitriteTextIndexer nitriteTextIndexer = new NitriteTextIndexer(); + + Fields fields = new Fields(); + fields.addField("Field"); + nitriteTextIndexer.validateIndex(fields); + assertEquals("[Field]", fields.toString()); + } + + @Test + public void testValidateIndex3() { + NitriteTextIndexer nitriteTextIndexer = new NitriteTextIndexer(); + + Fields fields = new Fields(); + fields.addField("Field"); + fields.addField("Field"); + assertThrows(IndexingException.class, () -> nitriteTextIndexer.validateIndex(fields)); + } + + @Test(expected = IndexingException.class) + public void testDropIndex() { + NitriteTextIndexer nitriteTextIndexer = new NitriteTextIndexer(); + Fields fields = mock(Fields.class); + when(fields.getEncodedName()).thenThrow(new IndexingException("An error occurred")); + IndexDescriptor indexDescriptor = new IndexDescriptor("Index Type", fields, "Collection Name"); + nitriteTextIndexer.dropIndex(indexDescriptor, new NitriteConfig()); + verify(fields).getEncodedName(); + assertFalse(indexDescriptor.isCompoundIndex()); + } + + @Test(expected = IndexingException.class) + public void testDropIndex2() { + NitriteTextIndexer nitriteTextIndexer = new NitriteTextIndexer(); + IndexDescriptor indexDescriptor = mock(IndexDescriptor.class); + when(indexDescriptor.getIndexType()).thenThrow(new IndexingException("An error occurred")); + when(indexDescriptor.getIndexFields()).thenReturn(new Fields()); + when(indexDescriptor.getCollectionName()).thenReturn("foo"); + nitriteTextIndexer.dropIndex(indexDescriptor, new NitriteConfig()); + verify(indexDescriptor).getIndexType(); + verify(indexDescriptor).getIndexFields(); + verify(indexDescriptor).getCollectionName(); + } + + @Test + public void testDropIndex3() { + NitriteTextIndexer nitriteTextIndexer = new NitriteTextIndexer(); + IndexDescriptor indexDescriptor = mock(IndexDescriptor.class); + when(indexDescriptor.getIndexType()).thenReturn("foo"); + when(indexDescriptor.getIndexFields()).thenReturn(new Fields()); + when(indexDescriptor.getCollectionName()).thenReturn("foo"); + NitriteConfig nitriteConfig = mock(NitriteConfig.class); + doReturn(new InMemoryStore()).when(nitriteConfig).getNitriteStore(); + nitriteTextIndexer.dropIndex(indexDescriptor, nitriteConfig); + verify(indexDescriptor).getIndexType(); + verify(indexDescriptor).getIndexFields(); + verify(indexDescriptor).getCollectionName(); + verify(nitriteConfig).getNitriteStore(); + } + + @Test + public void testWriteIndexEntry() { + NitriteTextIndexer nitriteTextIndexer = new NitriteTextIndexer(); + FieldValues fieldValues = new FieldValues(); + fieldValues.getValues().add(Pair.pair("a", "1")); + IndexDescriptor indexDescriptor = new IndexDescriptor("Index Type", Fields.withNames("a"), "Collection Name"); + NitriteConfig nitriteConfig = mock(NitriteConfig.class); + doReturn(new InMemoryStore()).when(nitriteConfig).getNitriteStore(); + nitriteTextIndexer.writeIndexEntry(fieldValues, indexDescriptor, nitriteConfig); + assertEquals("FieldValues(nitriteId=null, fields=[a], values=[Pair(first=a, second=1)])", fieldValues.toString()); + assertEquals("[a]", fieldValues.getFields().toString()); + } + + @Test + public void testRemoveIndexEntry() { + NitriteTextIndexer nitriteTextIndexer = new NitriteTextIndexer(); + FieldValues fieldValues = new FieldValues(); + fieldValues.getValues().add(Pair.pair("a", "1")); + IndexDescriptor indexDescriptor = new IndexDescriptor("Index Type", Fields.withNames("a"), "Collection Name"); + NitriteConfig nitriteConfig = mock(NitriteConfig.class); + doReturn(new InMemoryStore()).when(nitriteConfig).getNitriteStore(); + nitriteTextIndexer.removeIndexEntry(fieldValues, indexDescriptor, nitriteConfig); + assertEquals("FieldValues(nitriteId=null, fields=[a], values=[Pair(first=a, second=1)])", fieldValues.toString()); + assertEquals("[a]", fieldValues.getFields().toString()); + } + + @Test + public void testFindByFilter() { + NitriteTextIndexer nitriteTextIndexer = new NitriteTextIndexer(); + + FindPlan findPlan = new FindPlan(); + findPlan.setIndexDescriptor(new IndexDescriptor("Index Type", new Fields(), "Collection Name")); + assertTrue(nitriteTextIndexer.findByFilter(findPlan, new NitriteConfig()).isEmpty()); + } + + @Test + public void testFindByFilter2() { + NitriteTextIndexer nitriteTextIndexer = new NitriteTextIndexer(); + + FindPlan findPlan = new FindPlan(); + findPlan.setIndexScanFilter(null); + findPlan.setIndexDescriptor(new IndexDescriptor("Index Type", new Fields(), "Collection Name")); + assertTrue(nitriteTextIndexer.findByFilter(findPlan, new NitriteConfig()).isEmpty()); + } } diff --git a/nitrite/src/test/java/org/dizitart/no2/index/NonUniqueIndexerTest.java b/nitrite/src/test/java/org/dizitart/no2/index/NonUniqueIndexerTest.java index da4642b06..7b411d385 100644 --- a/nitrite/src/test/java/org/dizitart/no2/index/NonUniqueIndexerTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/index/NonUniqueIndexerTest.java @@ -1,11 +1,19 @@ package org.dizitart.no2.index; +import org.junit.Test; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import org.junit.Test; - public class NonUniqueIndexerTest { + + @Test + public void testConstructor() { + NonUniqueIndexer actualNonUniqueIndexer = new NonUniqueIndexer(); + assertEquals(IndexType.NON_UNIQUE, actualNonUniqueIndexer.getIndexType()); + assertFalse(actualNonUniqueIndexer.isUnique()); + } + @Test public void testIsUnique() { assertFalse((new NonUniqueIndexer()).isUnique()); diff --git a/nitrite/src/test/java/org/dizitart/no2/index/SingleFieldIndexTest.java b/nitrite/src/test/java/org/dizitart/no2/index/SingleFieldIndexTest.java new file mode 100644 index 000000000..b033fc100 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/index/SingleFieldIndexTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.index; + +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.common.FieldValues; +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.store.memory.InMemoryStore; +import org.junit.Test; + +import static org.dizitart.no2.common.tuples.Pair.pair; +import static org.junit.Assert.*; + +public class SingleFieldIndexTest { + @Test + public void testConstructor() { + IndexDescriptor indexDescriptor = new IndexDescriptor("Index Type", new Fields(), "Collection Name"); + assertSame(indexDescriptor, (new SingleFieldIndex(indexDescriptor, null)).getIndexDescriptor()); + } + + @Test + public void testWrite() { + SingleFieldIndex singleFieldIndex = new SingleFieldIndex( + new IndexDescriptor("Index Type", new Fields(), "Collection Name"), new InMemoryStore()); + FieldValues fieldValues = new FieldValues(); + fieldValues.getValues().add(pair("a", 1)); + singleFieldIndex.write(fieldValues); + assertEquals("FieldValues(nitriteId=null, fields=[a], values=[Pair(first=a, second=1)])", fieldValues.toString()); + assertEquals("[a]", fieldValues.getFields().toString()); + } + + @Test + public void testRemove() { + SingleFieldIndex singleFieldIndex = new SingleFieldIndex( + new IndexDescriptor("Index Type", new Fields(), "Collection Name"), new InMemoryStore()); + FieldValues fieldValues = new FieldValues(); + fieldValues.getValues().add(pair("a", 1)); + singleFieldIndex.remove(fieldValues); + assertEquals("FieldValues(nitriteId=null, fields=[a], values=[Pair(first=a, second=1)])", fieldValues.toString()); + assertEquals("[a]", fieldValues.getFields().toString()); + } + + @Test + public void testFindNitriteIds() { + SingleFieldIndex singleFieldIndex = new SingleFieldIndex( + new IndexDescriptor("Index Type", new Fields(), "Collection Name"), null); + assertTrue(singleFieldIndex.findNitriteIds(new FindPlan()).isEmpty()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/index/TextIndexTest.java b/nitrite/src/test/java/org/dizitart/no2/index/TextIndexTest.java new file mode 100644 index 000000000..1dfff7611 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/index/TextIndexTest.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.index; + +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.common.FieldValues; +import org.dizitart.no2.common.Fields; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.index.fulltext.EnglishTextTokenizer; +import org.dizitart.no2.store.memory.InMemoryStore; +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class TextIndexTest { + @Test + public void testConstructor() { + EnglishTextTokenizer textTokenizer = new EnglishTextTokenizer(); + IndexDescriptor indexDescriptor = new IndexDescriptor("Index Type", new Fields(), "Collection Name"); + assertSame(indexDescriptor, (new TextIndex(textTokenizer, indexDescriptor, null)).getIndexDescriptor()); + } + + @Test + public void testWrite() { + EnglishTextTokenizer textTokenizer = new EnglishTextTokenizer(); + TextIndex textIndex = new TextIndex(textTokenizer, + new IndexDescriptor("Index Type", new Fields(), "Collection Name"), new InMemoryStore()); + FieldValues fieldValues = new FieldValues(); + fieldValues.getValues().add(Pair.pair("a", "1")); + textIndex.write(fieldValues); + assertEquals("FieldValues(nitriteId=null, fields=[a], values=[Pair(first=a, second=1)])", fieldValues.toString()); + assertEquals("[a]", fieldValues.getFields().toString()); + } + + @Test + public void testRemove() { + EnglishTextTokenizer textTokenizer = new EnglishTextTokenizer(); + TextIndex textIndex = new TextIndex(textTokenizer, + new IndexDescriptor("Index Type", new Fields(), "Collection Name"), new InMemoryStore()); + FieldValues fieldValues = new FieldValues(); + fieldValues.getValues().add(Pair.pair("a", "1")); + textIndex.remove(fieldValues); + assertEquals("FieldValues(nitriteId=null, fields=[a], values=[Pair(first=a, second=1)])", fieldValues.toString()); + assertEquals("[a]", fieldValues.getFields().toString()); + } + + @Test(expected = IndexingException.class) + public void testDrop() { + Fields fields = mock(Fields.class); + when(fields.getEncodedName()).thenThrow(new IndexingException("An error occurred")); + IndexDescriptor indexDescriptor = new IndexDescriptor("Index Type", fields, "Collection Name"); + TextIndex textIndex = new TextIndex(new EnglishTextTokenizer(), indexDescriptor, null); + textIndex.drop(); + verify(fields).getEncodedName(); + assertFalse(textIndex.getIndexDescriptor().isCompoundIndex()); + } + + @Test + public void testDrop2() { + Fields fields = mock(Fields.class); + when(fields.getEncodedName()).thenReturn("foo"); + IndexDescriptor indexDescriptor = new IndexDescriptor("Index Type", fields, "Collection Name"); + EnglishTextTokenizer textTokenizer = new EnglishTextTokenizer(); + TextIndex textIndex = new TextIndex(textTokenizer, indexDescriptor, new InMemoryStore()); + textIndex.drop(); + verify(fields).getEncodedName(); + assertFalse(textIndex.getIndexDescriptor().isCompoundIndex()); + } + + @Test + public void testFindNitriteIds() { + EnglishTextTokenizer textTokenizer = new EnglishTextTokenizer(); + TextIndex textIndex = new TextIndex(textTokenizer, + new IndexDescriptor("Index Type", new Fields(), "Collection Name"), null); + assertTrue(textIndex.findNitriteIds(new FindPlan()).isEmpty()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/index/UniqueIndexerTest.java b/nitrite/src/test/java/org/dizitart/no2/index/UniqueIndexerTest.java index 12305e965..61ab9451d 100644 --- a/nitrite/src/test/java/org/dizitart/no2/index/UniqueIndexerTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/index/UniqueIndexerTest.java @@ -1,11 +1,18 @@ package org.dizitart.no2.index; +import org.junit.Test; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import org.junit.Test; - public class UniqueIndexerTest { + @Test + public void testConstructor() { + UniqueIndexer actualUniqueIndexer = new UniqueIndexer(); + assertEquals(IndexType.UNIQUE, actualUniqueIndexer.getIndexType()); + assertTrue(actualUniqueIndexer.isUnique()); + } + @Test public void testGetIndexType() { assertEquals("Unique", (new UniqueIndexer()).getIndexType()); diff --git a/nitrite/src/test/java/org/dizitart/no2/index/fulltext/TokenizerTests.java b/nitrite/src/test/java/org/dizitart/no2/index/fulltext/TokenizerTests.java index a8a0a6ea6..5d1fe83c2 100644 --- a/nitrite/src/test/java/org/dizitart/no2/index/fulltext/TokenizerTests.java +++ b/nitrite/src/test/java/org/dizitart/no2/index/fulltext/TokenizerTests.java @@ -16,7 +16,7 @@ package org.dizitart.no2.index.fulltext; -import org.dizitart.no2.Retry; +import org.dizitart.no2.integration.Retry; import org.junit.Rule; import org.junit.Test; diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/CustomFilterTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/CustomFilterTest.java new file mode 100644 index 000000000..75a15f156 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/CustomFilterTest.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.dizitart.no2.integration.collection.BaseCollectionTest; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee. + */ +public class CustomFilterTest extends BaseCollectionTest { + + @Test + public void testCustomFilter() { + insert(); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "firstName"); + DocumentCursor cursor = collection.find(element -> element.getSecond().get("firstName", String.class) + .equalsIgnoreCase("FN1")); + + assertEquals(cursor.size(), 1); + assertEquals(cursor.firstOrNull().get("firstName"), "fn1"); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/DbTestOperations.java b/nitrite/src/test/java/org/dizitart/no2/integration/DbTestOperations.java new file mode 100644 index 000000000..588ba57b7 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/DbTestOperations.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.index.IndexType; +import org.junit.Rule; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.*; + +import static org.dizitart.no2.integration.TestUtil.isSorted; +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.collection.FindOptions.orderBy; +import static org.dizitart.no2.filters.Filter.*; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee. + */ +public class DbTestOperations { + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + public static String getRandomTempDbFile() { + String dataDir = System.getProperty("java.io.tmpdir") + File.separator + "nitrite" + File.separator + "data"; + File file = new File(dataDir); + if (!file.exists()) { + assertTrue(file.mkdirs()); + } + return file.getPath() + File.separator + UUID.randomUUID().toString() + ".db"; + } + + void createDb() throws Exception { + db = TestUtil.createDb(); + db.close(); + } + + void writeCollection() throws Exception { + NitriteCollection collection; + + db = TestUtil.createDb(); + + collection = db.getCollection("test"); + collection.remove(ALL); + db.close(); + } + + void writeIndex() throws Exception { + NitriteCollection collection; + + db = TestUtil.createDb(); + + collection = db.getCollection("test"); + collection.remove(ALL); + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + collection.createIndex("firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + db.close(); + } + + void insertInCollection() throws Exception { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); + + Document doc1 = createDocument("firstName", "fn1") + .put("lastName", "ln1") + .put("birthDay", simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + .put("data", new byte[]{1, 2, 3}) + .put("body", "a quick brown fox jump over the lazy dog"); + Document doc2 = createDocument("firstName", "fn2") + .put("lastName", "ln2") + .put("birthDay", simpleDateFormat.parse("2010-06-12T16:02:48.440Z")) + .put("data", new byte[]{3, 4, 3}) + .put("body", "quick hello world from nitrite"); + Document doc3 = createDocument("firstName", "fn3") + .put("lastName", "ln2") + .put("birthDay", simpleDateFormat.parse("2014-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + + NitriteCollection collection; + + db = TestUtil.createDb(); + + collection = db.getCollection("test"); + + WriteResult result = collection.insert(doc1, doc2, doc3); + assertEquals(result.getAffectedCount(), 3); + + db.commit(); + db.close(); + } + + void readCollection() throws Exception { + NitriteCollection collection; + + db = TestUtil.createDb(); + + collection = db.getCollection("test"); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").gt(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").gte(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lt(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").lte(simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lte(new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").lt(new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").gt(new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("birthDay").gte(new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("birthDay").lte(new Date()).and(where("firstName").eq("fn1"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").lte(new Date()).or(where("firstName").eq("fn12"))); + assertEquals(cursor.size(), 3); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + )); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + ).not()); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").eq((byte) 4)); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").lt(4)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("firstName").notIn("fn1", "fn2")); + assertEquals(cursor.size(), 1); + + collection.createIndex("birthDay"); + cursor = collection.find(orderBy("birthDay", SortOrder.Descending).skip(1).limit(2)); + assertEquals(cursor.size(), 2); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, false)); + + cursor = collection.find(where("body").text("Lorem")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("body").text("quick")); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("body").text("nosql")); + assertEquals(cursor.size(), 0); + + db.close(); + } + + void deleteDb() throws Exception { + if (db != null && !db.isClosed()) { + db.close(); + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/DocumentMetadataTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/DocumentMetadataTest.java new file mode 100644 index 000000000..15d01451f --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/DocumentMetadataTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.dizitart.no2.integration.collection.BaseCollectionTest; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.events.EventType; +import org.junit.Test; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee. + */ +public class DocumentMetadataTest extends BaseCollectionTest { + @Test + public void testTimeStamp() { + Document document = createDocument("test_key", "test_value"); + assertEquals(document.getRevision().intValue(), 0); + assertEquals(document.getLastModifiedSinceEpoch().longValue(), 0L); + + collection.insert(document); + document = collection.find().firstOrNull(); + + assertEquals(document.getRevision().intValue(), 1); + assertTrue(document.getLastModifiedSinceEpoch() > 0); + + long previous = document.getRevision(); + + DocumentCursor cursor = collection.find(where("test_key").eq("test_value")); + document = cursor.firstOrNull(); + document.put("another_key", "another_value"); + + collection.update(document); + cursor = collection.find(where("test_key").eq("test_value")); + document = cursor.firstOrNull(); + + assertTrue(document.getRevision() > previous); + + final long time = document.getRevision(); + final Document removed = document; + + collection.subscribe(changeInfo -> { + if (changeInfo.getEventType() == EventType.Remove) { + assertTrue(removed.getRevision() > time); + } + }); + + collection.remove(document); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/MultiThreadedTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/MultiThreadedTest.java new file mode 100644 index 000000000..e2c3812e9 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/MultiThreadedTest.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.concurrent.ThreadPoolManager; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; + +import java.util.Date; +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.dizitart.no2.integration.DbTestOperations.getRandomTempDbFile; +import static org.dizitart.no2.integration.TestUtil.createDb; +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + + +/** + * @author Anindya Chatterjee. + */ +public class MultiThreadedTest { + private static final String fileName = getRandomTempDbFile(); + private NitriteCollection collection; + private final int threadCount = 20; + private final CountDownLatch latch = new CountDownLatch(threadCount); + private final int iterationCount = 100; + private final Random generator = new Random(); + private final AtomicInteger docCounter = new AtomicInteger(0); + private ExecutorService executor = ThreadPoolManager.getThreadPool(threadCount, "MultiThreadedTest"); + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Test + public void testOperations() throws Exception { + db = createDb(); + + collection = db.getCollection("test"); + collection.remove(Filter.ALL); + collection.createIndex("unixTime"); + db.commit(); + + for (int i = 0; i < threadCount; i++) { + executor.submit(() -> { + for (int j = 0; j < iterationCount; j++) { + try { + Document document = generate(); + collection.insert(document); + + if (j == iterationCount / 2 + && !collection.hasIndex("text") + && !collection.hasIndex("date")) { + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "text"); + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "date"); + } + + long unixTime = (long) document.get("unixTime"); + DocumentCursor cursor = collection.find(where("unixTime").eq(unixTime)); + assertTrue(cursor.size() >= 0); + + if (collection.hasIndex("text") && !collection.isIndexing("text")) { + String textData = (String) document.get("text"); + cursor = collection.find(where("text").text(textData)); + assertTrue(cursor.size() >= 0); + } + + assertTrue(collection.hasIndex("unixTime")); + } catch (Throwable e) { + System.out.println("Exception at thread " + + Thread.currentThread().getName() + " with iteration " + j); + e.printStackTrace(); + } + } + latch.countDown(); + }); + } + + latch.await(); + + db.commit(); + + assertTrue(collection.hasIndex("text")); + assertTrue(collection.hasIndex("date")); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), docCounter.get()); + + cursor = collection.find(where("unixTime").gt(1L)); + assertEquals(cursor.size(), docCounter.get()); + + db.close(); + } + + @After + public void cleanUp() throws Exception { + if (db != null && !db.isClosed()) { + db.close(); + } + + if (executor != null && !executor.isShutdown()) { + executor.shutdown(); + executor = null; + } + } + + private synchronized Document generate() { + Document document = createDocument("unixTime", System.nanoTime() + docCounter.incrementAndGet()); + byte[] blob = new byte[1024]; + generator.nextBytes(blob); + document.put("blob", blob); + document.put("text", UUID.randomUUID().toString().replaceAll("-", " ")); + document.put("date", new Date()); + return document; + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/NitriteCorruptedTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/NitriteCorruptedTest.java new file mode 100644 index 000000000..21a2d5731 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/NitriteCorruptedTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.concurrent.ThreadPoolManager; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.util.concurrent.ExecutorService; + +import static org.dizitart.no2.integration.TestUtil.createDb; +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.Filter.ALL; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee + */ +public class NitriteCorruptedTest { + private Nitrite db; + private NitriteCollection collection; + private Thread thread; + private final ExecutorService dbPool = ThreadPoolManager.getThreadPool(Runtime.getRuntime().availableProcessors(), + "NitriteCorruptedTest"); + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + db = createDb(); + + collection = db.getCollection("test"); + collection.remove(ALL); + + thread = new Thread(() -> { + for (int i = 0; i < 50000; i++) { + + // Interruption Guard + if (Thread.interrupted()) { + break; + } + + Document doc1 = createDocument(String.valueOf(System.currentTimeMillis()), "fn1") + .put("lastName", "ln1") + .put("data", new byte[]{1, 2, 3}) + .put("body", "a quick brown fox jump over the lazy dog"); + + // Separate user thread from Db write thread + dbPool.submit(() -> collection.insert(doc1)); + } + }); + } + + @After + public void tearDown() throws Exception { + if (collection.isOpen()) { + collection.remove(ALL); + collection.close(); + } + db.close(); + } + + @Test(timeout = 10000) + public void issue118() throws InterruptedException { + thread.start(); + Thread.sleep(10); + thread.interrupt(); + Thread.sleep(500); + assertTrue(collection.isOpen()); + assertFalse(db.isClosed()); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/NitriteSecurityTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/NitriteSecurityTest.java new file mode 100644 index 000000000..df0242dcc --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/NitriteSecurityTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.NitriteCollection; +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; + +import static org.dizitart.no2.integration.TestUtil.createDb; +import static org.dizitart.no2.collection.Document.createDocument; +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee. + */ +public class NitriteSecurityTest { + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Test + public void testInMemory() throws Exception { + db = createDb("test-user", "test-password"); + NitriteCollection dbCollection = db.getCollection("test"); + dbCollection.insert(createDocument("test", "test")); + db.commit(); + assertEquals(dbCollection.find().size(), 1); + db.close(); + + db = createDb(); + dbCollection = db.getCollection("test"); + assertEquals(dbCollection.find().size(), 0); + db.close(); + } + + @After + public void cleanUp() throws Exception { + if (db != null && !db.isClosed()) { + db.close(); + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/NitriteStressTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/NitriteStressTest.java new file mode 100644 index 000000000..afc769d96 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/NitriteStressTest.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import lombok.Data; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Id; +import org.junit.Rule; +import org.junit.Test; +import uk.co.jemos.podam.api.PodamFactory; +import uk.co.jemos.podam.api.PodamFactoryImpl; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import java.util.ArrayList; +import java.util.List; + +import static org.dizitart.no2.integration.TestUtil.createDb; + + +/** + * @author Anindya Chatterjee + */ +public class NitriteStressTest { + private static final int TEST_SET_COUNT = 15000; + private final PodamFactory podamFactory = new PodamFactoryImpl(); + + @Rule + public Retry retry = new Retry(3); + + @Test + public void stressTest() { + Nitrite database = createDb(); + ObjectRepository testRepository = database.getRepository(TestDto.class); + testRepository.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "lastName"); + testRepository.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "birthDate"); + + int counter = 0; + try { + for (TestDto testDto : createTestSet()) { + testRepository.insert(testDto); + counter++; + } + } catch (Throwable t) { + System.err.println("Crashed after " + counter + " records"); + throw t; + } + } + + private List createTestSet() { + List testData = new ArrayList<>(); + for (int i = 0; i < TEST_SET_COUNT; i++) { + TestDto testRecords = podamFactory.manufacturePojo(TestDto.class); + testData.add(testRecords); + } + return testData; + } + + @Data + public static class TestDto implements Mappable { + + @XmlElement( + name = "StudentNumber", + required = true + ) + @Id + protected String studentNumber; + + @XmlElement( + name = "LastName", + required = true + ) + protected String lastName; + + @XmlElement( + name = "Prefixes" + ) + protected String prefixes; + + @XmlElement( + name = "Initials", + required = true + ) + protected String initials; + + @XmlElement( + name = "FirstNames" + ) + protected String firstNames; + @XmlElement( + name = "Nickname" + ) + protected String nickName; + + @XmlElement( + name = "BirthDate", + required = true + ) + @XmlSchemaType( + name = "date" + ) + protected String birthDate; + + + public TestDto() { + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("studentNumber", studentNumber) + .put("lastName", lastName) + .put("prefixes", prefixes) + .put("initials", initials) + .put("firstNames", firstNames) + .put("nickName", nickName) + .put("birthDate", birthDate); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + studentNumber = document.get("studentNumber", String.class); + lastName = document.get("lastName", String.class); + prefixes = document.get("prefixes", String.class); + initials = document.get("initials", String.class); + firstNames = document.get("firstNames", String.class); + nickName = document.get("nickName", String.class); + birthDate = document.get("birthDate", String.class); + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/NitriteTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/NitriteTest.java new file mode 100644 index 000000000..9e698a829 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/NitriteTest.java @@ -0,0 +1,438 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.FindOptions; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.UpdateOptions; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.common.concurrent.ThreadPoolManager; +import org.dizitart.no2.exceptions.NitriteIOException; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; +import org.dizitart.no2.repository.annotations.Indices; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import uk.co.jemos.podam.api.PodamFactory; +import uk.co.jemos.podam.api.PodamFactoryImpl; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Locale; +import java.util.Random; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; + +import static org.dizitart.no2.integration.TestUtil.createDb; +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.common.Constants.INTERNAL_NAME_SEPARATOR; +import static org.dizitart.no2.common.Constants.META_MAP_NAME; +import static org.dizitart.no2.filters.Filter.ALL; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class NitriteTest { + @Rule + public Retry retry = new Retry(3); + private Nitrite db; + private NitriteCollection collection; + + @Before + public void setUp() throws ParseException { + db = createDb("test-user", "test-password"); + + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); + + Document doc1 = createDocument("firstName", "fn1") + .put("lastName", "ln1") + .put("birthDay", simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + .put("data", new byte[]{1, 2, 3}) + .put("body", "a quick brown fox jump over the lazy dog"); + Document doc2 = createDocument("firstName", "fn2") + .put("lastName", "ln2") + .put("birthDay", simpleDateFormat.parse("2010-06-12T16:02:48.440Z")) + .put("data", new byte[]{3, 4, 3}) + .put("body", "hello world from nitrite"); + Document doc3 = createDocument("firstName", "fn3") + .put("lastName", "ln2") + .put("birthDay", simpleDateFormat.parse("2014-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + + collection = db.getCollection("test"); + collection.remove(ALL); + + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "firstName"); + collection.insert(doc1, doc2, doc3); + } + + @After + public void tearDown() throws Exception { + if (collection.isOpen()) { + collection.remove(ALL); + collection.close(); + } + if (db != null && !db.isClosed()) { + try { + db.close(); + } catch (NitriteIOException ignore) { + } + } + } + + @Test + public void testListCollectionNames() { + Set collectionNames = db.listCollectionNames(); + assertEquals(collectionNames.size(), 1); + } + + @Test + public void testListRepositories() { + db.getRepository(getClass()); + Set repositories = db.listRepositories(); + assertEquals(repositories.size(), 1); + } + + @Test + public void testHasCollection() { + assertTrue(db.hasCollection("test")); + assertFalse(db.hasCollection("lucene" + INTERNAL_NAME_SEPARATOR + "test")); + } + + @Test + public void testHasRepository() { + db.getRepository(getClass()); + assertTrue(db.hasRepository(getClass())); + assertFalse(db.hasRepository(String.class)); + } + + @Test + public void testClose() throws Exception { + NitriteCollection testCollection = db.getCollection("test"); + testCollection.insert(createDocument("a", "b")); + db.close(); + + assertFalse(testCollection.isOpen()); + } + + @Test + public void testGetCollection() { + NitriteCollection collection = db.getCollection("test-collection"); + assertNotNull(collection); + assertEquals(collection.getName(), "test-collection"); + } + + @Test + public void testGetRepository() { + ObjectRepository repository = db.getRepository(NitriteTest.class); + assertNotNull(repository); + assertEquals(repository.getType(), NitriteTest.class); + } + + @Test + public void testGetRepositoryWithKey() { + ObjectRepository repository = db.getRepository(NitriteTest.class, "key"); + assertNotNull(repository); + assertEquals(repository.getType(), NitriteTest.class); + assertFalse(db.hasRepository(NitriteTest.class)); + assertTrue(db.hasRepository(NitriteTest.class, "key")); + } + + @Test + public void testMultipleGetCollection() { + NitriteCollection collection = db.getCollection("test-collection"); + assertNotNull(collection); + assertEquals(collection.getName(), "test-collection"); + + NitriteCollection collection2 = db.getCollection("test-collection"); + assertNotNull(collection2); + assertEquals(collection2.getName(), "test-collection"); + } + + @Test + public void testMultipleGetRepository() { + ObjectRepository repository = db.getRepository(NitriteTest.class); + assertNotNull(repository); + assertEquals(repository.getType(), NitriteTest.class); + + ObjectRepository repository2 = db.getRepository(NitriteTest.class); + assertNotNull(repository2); + assertEquals(repository2.getType(), NitriteTest.class); + } + + @Test(expected = ValidationException.class) + public void testGetRepositoryInvalid() { + db.getRepository(null); + } + + @Test(expected = NitriteIOException.class) + public void testGetCollectionNullStore() throws Exception { + db = Nitrite.builder().openOrCreate(); + db.close(); + db.getCollection("test"); + } + + @Test(expected = NitriteIOException.class) + public void testGetRepositoryNullStore() throws Exception { + db = Nitrite.builder().openOrCreate(); + db.close(); + db.getRepository(NitriteTest.class); + } + + @Test(expected = NitriteIOException.class) + public void testGetKeyedRepositoryNullStore() throws Exception { + db = Nitrite.builder().openOrCreate(); + db.close(); + db.getRepository(NitriteTest.class, "key"); + } + + @Test(expected = NitriteIOException.class) + public void testCommitNullStore() throws Exception { + db = Nitrite.builder().openOrCreate(); + db.close(); + db.commit(); + } + + @Test(expected = ValidationException.class) + public void testGetCollectionInvalidName() { + db.getCollection(META_MAP_NAME); + } + + @Test + public void testIssue185() throws InterruptedException { + final ObjectRepository repository = db.getRepository(Receipt.class); + final Receipt receipt = new Receipt(); + receipt.clientRef = "111-11111"; + receipt.status = Receipt.Status.PREPARING; + CountDownLatch latch = new CountDownLatch(1); + + new Thread(() -> { + for (int i = 0; i < 1000; ++i) { + try { + repository.update(receipt, true); + try { + Thread.sleep(5); + } catch (InterruptedException ignored) { + } + repository.remove(receipt); + try { + Thread.sleep(5); + } catch (InterruptedException ignored) { + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + latch.countDown(); + }).start(); + + for (int i = 0; i < 1000; ++i) { + repository.find(where("status").eq(Receipt.Status.COMPLETED).not(), + FindOptions.orderBy("createdTimestamp", SortOrder.Descending)).toList(); + try { + Thread.sleep(5); + } catch (InterruptedException ignored) { + } + } + latch.await(); + } + + @Test + public void testIssue193() throws InterruptedException { + final ObjectRepository repository = db.getRepository(Receipt.class); + final PodamFactory factory = new PodamFactoryImpl(); + final String[] refs = new String[]{"1", "2", "3", "4", "5"}; + final Random random = new Random(); + ExecutorService pool = ThreadPoolManager.workerPool(); + + final CountDownLatch latch = new CountDownLatch(10000); + for (int i = 0; i < 10000; i++) { + pool.submit(() -> { + try { + int refIndex = random.nextInt(5); + Receipt receipt = factory.manufacturePojoWithFullData(Receipt.class); + receipt.setClientRef(refs[refIndex]); + repository.update(receipt, true); + latch.countDown(); + } catch (Throwable t) { + t.printStackTrace(); + } + }); + } + + latch.await(); + assertTrue(repository.find().size() <= 5); + pool.shutdown(); + } + + @Test + public void testIssue212() { + NitriteCollection collection = db.getCollection("testIssue212"); + Document doc1 = createDocument("key", "key").put("second_key", "second_key").put("third_key", "third_key"); + Document doc2 = createDocument("key", "key").put("second_key", "second_key").put("fourth_key", "fourth_key"); + Document doc = createDocument("fifth_key", "fifth_key"); + + if (!collection.hasIndex("key")) { + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "key"); + } + if (!collection.hasIndex("second_key")) { + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "second_key"); + } + + collection.insert(doc1, doc2); + collection.update(where("key").eq("key").and(where("second_key").eq("second_key")), + doc, UpdateOptions.updateOptions(true)); + + for (Document document : collection.find()) { + System.out.println(document); + } + } + + @Test + public void testIssue245() throws Exception { + class ThreadRunner implements Runnable { + @Override + public void run() { + try { + long id = Thread.currentThread().getId(); + NitriteCollection collection = db.getCollection("testIssue245"); + + for (int i = 0; i < 5; i++) { + + System.out.println("Thread ID = " + id + " Inserting doc " + i); + Document doc = Document.createDocument(UUID.randomUUID().toString(), UUID.randomUUID().toString()); + + WriteResult result = collection.insert(doc);//db.commit(); + System.out.println("Result of insert = " + result.getAffectedCount()); + System.out.println("Thread id = " + id + " --> count = " + collection.size()); + + Thread.sleep(10); + + }//for closing + + collection.close(); + + } catch (Exception e) { + e.printStackTrace(); + } + } + }; + + Thread t0 = new Thread(new ThreadRunner()); + Thread t1 = new Thread(new ThreadRunner()); + Thread t2 = new Thread(new ThreadRunner()); + + t0.start(); + t1.start(); + t2.start(); + + Thread.sleep(10 * 1000); + + t0.join(); + t1.join(); + t2.join(); + + NitriteCollection collection = db.getCollection("testIssue245"); + System.out.println("No of Documents = " + collection.size()); + collection.close(); + db.close(); + } + + @Data + @AllArgsConstructor + @NoArgsConstructor + public static class CompatChild implements Mappable { + private Long childId; + private String lastName; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("childId", childId) + .put("lastName", lastName); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + childId = document.get("childId", Long.class); + lastName = document.get("lastName", String.class); + } + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Indices({ + @Index(value = "synced", type = IndexType.NON_UNIQUE) + }) + public static class Receipt implements Mappable { + @Id + private String clientRef; + private Boolean synced; + private Long createdTimestamp = System.currentTimeMillis(); + private Status status; + + @Override + public Document write(NitriteMapper mapper) { + return createDocument("status", status) + .put("clientRef", clientRef) + .put("synced", synced) + .put("createdTimestamp", createdTimestamp); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + if (document != null) { + Object status = document.get("status"); + if (status instanceof Status) { + this.status = (Status) status; + } else { + this.status = Status.valueOf(status.toString()); + } + this.clientRef = document.get("clientRef", String.class); + this.synced = document.get("synced", Boolean.class); + this.createdTimestamp = document.get("createdTimestamp", Long.class); + } + } + + public enum Status { + COMPLETED, + PREPARING, + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/Retry.java b/nitrite/src/test/java/org/dizitart/no2/integration/Retry.java new file mode 100644 index 000000000..3d6a27d11 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/Retry.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * @author Anindya Chatterjee + */ +public class Retry implements TestRule { + private final int retryCount; + + public Retry(int retryCount) { + this.retryCount = retryCount; + } + + public Statement apply(Statement base, Description description) { + return statement(base, description); + } + + private Statement statement(final Statement base, final Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + Throwable caughtThrowable = null; + + // implement retry logic here + for (int i = 0; i < retryCount; i++) { + try { + base.evaluate(); + return; + } catch (Throwable t) { + caughtThrowable = t; + System.err.println(description.getDisplayName() + ": run " + (i + 1) + " failed"); + } + } + System.err.println(description.getDisplayName() + ": giving up after " + retryCount + " failures"); + throw caughtThrowable; + } + }; + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/SerializabilityTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/SerializabilityTest.java new file mode 100644 index 000000000..7a759aeb3 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/SerializabilityTest.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import lombok.Data; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.exceptions.ValidationException; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.Serializable; + +import static org.dizitart.no2.integration.TestUtil.createDb; + +/** + * @author Anindya Chatterjee + */ +public class SerializabilityTest { + private NitriteCollection collection; + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + db = createDb(); + collection = db.getCollection("test"); + } + + @After + public void tearDown() throws Exception { + if (db != null && !db.isClosed()) { + db.close(); + } + } + + @Test(expected = ValidationException.class) + public void testSerializabilityValidation() { + for (int i = 0; i < 5; i++) { + Document doc = Document.createDocument(); + doc.put("key", i); + doc.put("data", new NotSerializableClass(Integer.toString(i))); + collection.insert(doc); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("Write " + i + " completed"); + } + } + + @Test + public void testSerializablity() { + for (int i = 0; i < 5; i++) { + Document doc = Document.createDocument(); + doc.put("key", i); + doc.put("data", new SerializableClass(Integer.toString(i))); + collection.insert(doc); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("Write " + i + " completed"); + } + } + + @Data + public static class NotSerializableClass { + private String myId; + + public NotSerializableClass(String myId) { + this.myId = myId; + } + } + + @Data + public static class SerializableClass implements Serializable { + private String myId; + + public SerializableClass(String myId) { + this.myId = myId; + } + } +} + + diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/StressTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/StressTest.java new file mode 100644 index 000000000..65142470c --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/StressTest.java @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import lombok.Data; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Index; +import org.dizitart.no2.repository.annotations.Indices; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import uk.co.jemos.podam.api.PodamFactory; +import uk.co.jemos.podam.api.PodamFactoryImpl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.atomic.AtomicLong; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * @author Anindya Chatterjee + */ +public class StressTest { + private Nitrite db; + private NitriteCollection collection; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void before() { + db = Nitrite.builder() + .fieldSeparator(".") + .openOrCreate(); + + collection = db.getCollection("test"); + } + + @Test + public void testIssue41() { + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "number"); + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "name"); + collection.createIndex("counter"); + + Random random = new Random(); + AtomicLong counter = new AtomicLong(System.currentTimeMillis()); + PodamFactory factory = new PodamFactoryImpl(); + + long start = System.currentTimeMillis(); + for (int i = 0; i < 100000; i++) { + Document doc = Document.createDocument(); + doc.put("number", random.nextDouble()); + doc.put("name", factory.manufacturePojo(String.class)); + doc.put("counter", counter.getAndIncrement()); + collection.insert(doc); + if (i % 10000 == 0) { + System.out.println(i + " entries written"); + } + } + System.out.println("Records inserted in " + ((System.currentTimeMillis() - start) / (1000 * 60)) + " minutes"); + + if (db.hasUnsavedChanges()) { + db.commit(); + } + + start = System.currentTimeMillis(); + DocumentCursor cursor = collection.find(); + System.out.println("Size ->" + cursor.size()); + System.out.println("Records size calculated in " + ((System.currentTimeMillis() - start) / (1000)) + " seconds"); + + int i = 0; + start = System.currentTimeMillis(); + for (Document element : cursor) { + assertNotNull(element); + i++; + if (i % 10000 == 0) { + System.out.println(i + " entries processed"); + } + } + System.out.println("Iteration completed in " + ((System.currentTimeMillis() - start) / (1000)) + " seconds"); + } + + @After + public void clear() throws Exception { + if (db != null && !db.isClosed()) { + long start = System.currentTimeMillis(); + db.close(); + System.out.println("Time to compact and close - " + (System.currentTimeMillis() - start) / 1000 + " seconds"); + } + } + + @Test + public void testRepoPerformanceWithIndex() { + // warm-up + List items = getItems(PerfTestIndexed.class); + ObjectRepository repo = db.getRepository(PerfTestIndexed.class); + for (PerfTestIndexed item : items) { + assertNotNull(item); + repo.insert(item); + } + repo.remove(Filter.ALL); + repo.drop(); + + // actual calculation + repo = db.getRepository(PerfTestIndexed.class); + long start = System.currentTimeMillis(); + for (PerfTestIndexed item : items) { + repo.insert(item); + } + long diff = System.currentTimeMillis() - start; + System.out.println("Time take to insert 10000 indexed items - " + diff + "ms"); + + start = System.currentTimeMillis(); + repo.remove(Filter.ALL); + diff = System.currentTimeMillis() - start; + System.out.println("Time take to remove 10000 indexed items - " + diff + "ms"); + } + + @Test + public void testRepoPerformanceWithoutIndex() { + // warm-up + List items = getItems(PerfTest.class); + ObjectRepository repo = db.getRepository(PerfTest.class); + for (PerfTest item : items) { + assertNotNull(item); + repo.insert(item); + } + repo.remove(Filter.ALL); + repo.drop(); + + // actual calculation + repo = db.getRepository(PerfTest.class); + long start = System.currentTimeMillis(); + for (PerfTest item : items) { + repo.insert(item); + } + long diff = System.currentTimeMillis() - start; + System.out.println("Time take to insert 10000 non-indexed items - " + diff + "ms"); + + start = System.currentTimeMillis(); + repo.remove(Filter.ALL); + diff = System.currentTimeMillis() - start; + System.out.println("Time take to remove 10000 non-indexed items - " + diff + "ms"); + } + + private List getItems(Class type) { + PodamFactory generator = new PodamFactoryImpl(); + List items = new ArrayList<>(); + for (int i = 0; i < 10000; i++) { + items.add(generator.manufacturePojoWithFullData(type)); + } + assertEquals(items.size(), 10000); + return items; + } + + @Data + public static class PerfTest implements Mappable { + private String firstName; + private String lastName; + private Integer age; + private String text; + + @Override + public Document write(NitriteMapper mapper) { + Document document = Document.createDocument(); + document.put("firstName", firstName); + document.put("lastName", lastName); + document.put("age", age); + document.put("text", text); + return document; + } + + @Override + public void read(NitriteMapper mapper, Document document) { + this.firstName = (String) document.get("firstName"); + this.lastName = (String) document.get("lastName"); + this.age = (Integer) document.get("age"); + this.text = (String) document.get("text"); + } + } + + @Indices({ + @Index(value = "firstName", type = IndexType.NON_UNIQUE), + @Index(value = "age", type = IndexType.NON_UNIQUE), + @Index(value = "text", type = IndexType.FULL_TEXT), + }) + private static class PerfTestIndexed extends PerfTest { + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/TestUtil.java b/nitrite/src/test/java/org/dizitart/no2/integration/TestUtil.java new file mode 100644 index 000000000..c1d9e4b89 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/TestUtil.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.exceptions.ObjectMappingException; + +import java.io.IOException; +import java.util.*; + +/** + * @author Anindya Chatterjee + */ +@Slf4j +public class TestUtil { + + /** + * Determines whether the supplied `iterable` is sorted. + * + * @param the type parameter + * @param iterable the iterable + * @param ascending a boolean value indicating whether to sort in ascending order + * @return the boolean value indicating if `iterable` is sorted or not. + */ + public static > boolean isSorted(Iterable iterable, boolean ascending) { + Iterator iterator = iterable.iterator(); + if (!iterator.hasNext()) { + return true; + } + T t = iterator.next(); + while (iterator.hasNext()) { + T t2 = iterator.next(); + if (ascending) { + if (t.compareTo(t2) > 0) { + return false; + } + } else { + if (t.compareTo(t2) < 0) { + return false; + } + } + t = t2; + } + return true; + } + + public static Nitrite createDb() { + return Nitrite.builder() + .fieldSeparator(".") + .openOrCreate(); + } + + public static Nitrite createDb(String user, String password) { + return Nitrite.builder() + .fieldSeparator(".") + .openOrCreate(user, password); + } + + public static Document parse(String json) { + try { + ObjectMapper objectMapper = createObjectMapper(); + JsonNode node = objectMapper.readValue(json, JsonNode.class); + return loadDocument(node); + } catch (IOException e) { + log.error("Error while parsing json", e); + throw new ObjectMappingException("failed to parse json " + json); + } + } + + private static Document loadDocument(JsonNode node) { + Map objectMap = new LinkedHashMap<>(); + Iterator> fields = node.fields(); + while (fields.hasNext()) { + Map.Entry entry = fields.next(); + String name = entry.getKey(); + JsonNode value = entry.getValue(); + Object object = loadObject(value); + objectMap.put(name, object); + } + + return Document.createDocument(objectMap); + } + + private static Object loadObject(JsonNode node) { + if (node == null) + return null; + try { + switch (node.getNodeType()) { + case ARRAY: + return loadArray(node); + case BINARY: + return node.binaryValue(); + case BOOLEAN: + return node.booleanValue(); + case MISSING: + case NULL: + return null; + case NUMBER: + return node.numberValue(); + case OBJECT: + case POJO: + return loadDocument(node); + case STRING: + return node.textValue(); + } + } catch (IOException e) { + return null; + } + return null; + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private static List loadArray(JsonNode array) { + if (array.isArray()) { + List list = new ArrayList(); + Iterator iterator = array.elements(); + while (iterator.hasNext()) { + Object element = iterator.next(); + if (element instanceof JsonNode) { + list.add(loadObject((JsonNode) element)); + } else { + list.add(element); + } + } + return list; + } + return null; + } + + + private static ObjectMapper createObjectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.setVisibility( + objectMapper.getSerializationConfig().getDefaultVisibilityChecker() + .withFieldVisibility(JsonAutoDetect.Visibility.ANY) + .withGetterVisibility(JsonAutoDetect.Visibility.NONE) + .withIsGetterVisibility(JsonAutoDetect.Visibility.NONE)); + objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); + objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); + objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + objectMapper.findAndRegisterModules(); + return objectMapper; + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/collection/BaseCollectionTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/collection/BaseCollectionTest.java new file mode 100644 index 000000000..9dee23797 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/collection/BaseCollectionTest.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import lombok.extern.slf4j.Slf4j; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteBuilder; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.integration.Retry; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Collection; +import java.util.Locale; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.Filter.ALL; + +@Slf4j +@RunWith(value = Parameterized.class) +public abstract class BaseCollectionTest { + @Parameterized.Parameter + public boolean isSecured = false; + + protected Nitrite db; + protected NitriteCollection collection; + protected Document doc1, doc2, doc3; + protected SimpleDateFormat simpleDateFormat; + + @Rule + public Retry retry = new Retry(3); + + @Parameterized.Parameters(name = "Secured = {0}") + public static Collection data() { + return Arrays.asList(new Object[][]{ + {false}, + {true}, + }); + } + + @Before + public void setUp() { + try { + openDb(); + + simpleDateFormat + = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); + + doc1 = createDocument("firstName", "fn1") + .put("lastName", "ln1") + .put("birthDay", simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + .put("data", new byte[]{1, 2, 3}) + .put("list", Arrays.asList("one", "two", "three")) + .put("body", "a quick brown fox jump over the lazy dog"); + doc2 = createDocument("firstName", "fn2") + .put("lastName", "ln2") + .put("birthDay", simpleDateFormat.parse("2010-06-12T16:02:48.440Z")) + .put("data", new byte[]{3, 4, 3}) + .put("list", Arrays.asList("three", "four", "three")) + .put("body", "quick hello world from nitrite"); + doc3 = createDocument("firstName", "fn3") + .put("lastName", "ln2") + .put("birthDay", simpleDateFormat.parse("2014-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + + collection = db.getCollection("test"); + collection.remove(ALL); + } catch (Throwable t) { + log.error("Error while initializing test database", t); + } + } + + @After + public void clear() { + try { + if (collection != null && !collection.isDropped()) { + collection.close(); + } + if (db != null && !db.isClosed()) db.close(); + } catch (Throwable t) { + log.error("Error while clearing test database", t); + } + } + + private void openDb() { + NitriteBuilder nitriteBuilder = Nitrite.builder() + .fieldSeparator("."); + + if (isSecured) { + db = nitriteBuilder.openOrCreate("test-user", "test-password"); + } else { + db = nitriteBuilder.openOrCreate(); + } + } + + protected WriteResult insert() { + return collection.insert(doc1, doc2, doc3); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexNegativeTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexNegativeTest.java new file mode 100644 index 000000000..746fe397b --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexNegativeTest.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.exceptions.UniqueConstraintException; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Date; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee + */ +public class CollectionCompoundIndexNegativeTest extends BaseCollectionTest { + + @Test(expected = UniqueConstraintException.class) + public void testCreateInvalidUniqueIndex() { + doc1 = createDocument("firstName", "fn3") + .put("lastName", "ln2") + .put("birthDay", new Date()) + .put("data", new byte[]{1, 2, 3}) + .put("list", Arrays.asList("one", "two", "three")) + .put("body", "a quick brown fox jump over the lazy dog"); + + collection.createIndex("lastName", "firstName"); + insert(); + } + + @Test(expected = UniqueConstraintException.class) + public void testCreateUniqueMultiKeyIndexOnArray() { + collection.createIndex("data", "lastName"); + insert(); + } + + @Test(expected = UniqueConstraintException.class) + public void testCreateOnInvalidField() { + insert(); + // multiple null value will be created + collection.createIndex( "my-value", "lastName"); + } + + @Test(expected = IndexingException.class) + public void testDropIndexOnNonIndexedField() { + collection.dropIndex("data", "firstName"); + } + + @Test(expected = IndexingException.class) + public void testRebuildIndexInvalid() { + collection.rebuildIndex("unknown", "firstName"); + } + + @Test(expected = IndexingException.class) + public void createMultipleIndexTypeOnSameFields() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "lastName", "firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName", "firstName"); + } + + @Test(expected = IndexingException.class) + public void testIndexAlreadyExists() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName", "lastName"); + assertTrue(collection.hasIndex("firstName")); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "firstName", "lastName"); + } + + @Test(expected = IndexingException.class) + public void testCreateCompoundTextIndex() { + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body", "lastName"); + } + + @Test(expected = IndexingException.class) + public void testCreateMultiKeyIndexSecondField() { + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName", "data"); + assertTrue(collection.hasIndex("lastName")); + + insert(); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexTest.java new file mode 100644 index 000000000..e0ce0646a --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionCompoundIndexTest.java @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Date; +import java.util.Random; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.awaitility.Awaitility.await; +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.Filter.and; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class CollectionCompoundIndexTest extends BaseCollectionTest { + @Test + public void testCreateAndCheckIndex() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName", "lastName"); + assertTrue(collection.hasIndex("firstName")); + assertTrue(collection.hasIndex("firstName", "lastName")); + assertFalse(collection.hasIndex("firstName", "lastName", "birthDay")); + assertFalse(collection.hasIndex("lastName")); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + insert(); + } + + @Test + public void testCreateMultiKeyIndexFirstField() { + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "data", "lastName"); + assertTrue(collection.hasIndex("data")); + assertTrue(collection.hasIndex("data", "lastName")); + assertFalse(collection.hasIndex("lastName")); + + insert(); + } + + @Test + public void testListIndexes() { + assertEquals(collection.listIndices().size(), 0); + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName", "lastName"); + assertEquals(collection.listIndices().size(), 1); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "firstName"); + assertEquals(collection.listIndices().size(), 2); + } + + @Test + public void testDropIndex() { + collection.createIndex("firstName", "lastName"); + assertTrue(collection.hasIndex("firstName", "lastName")); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.dropIndex("firstName"); + assertTrue(collection.hasIndex("firstName", "lastName")); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex("firstName"); + collection.dropIndex("firstName", "lastName"); + assertFalse(collection.hasIndex("firstName", "lastName")); + assertTrue(collection.hasIndex("firstName")); + + collection.dropIndex("firstName"); + assertFalse(collection.hasIndex("firstName")); + assertEquals(collection.listIndices().size(), 0); + } + + @Test + public void testHasIndex() { + assertFalse(collection.hasIndex("lastName")); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName", "firstName"); + assertTrue(collection.hasIndex("lastName")); + } + + @Test + public void testDropAllIndexes() { + collection.dropAllIndices(); + + collection.createIndex("firstName", "lastName"); + collection.createIndex("firstName"); + assertEquals(collection.listIndices().size(), 2); + + collection.dropAllIndices(); + assertEquals(collection.listIndices().size(), 0); + } + + @Test + public void testRebuildIndex() { + collection.createIndex("firstName", "lastName"); + assertTrue(collection.hasIndex("firstName", "lastName")); + assertTrue(collection.hasIndex("firstName")); + + insert(); + collection.rebuildIndex("firstName", "lastName"); + assertTrue(collection.hasIndex("firstName", "lastName")); + assertTrue(collection.hasIndex("firstName")); + } + + @Test + public void testDeleteWithIndex() { + collection.createIndex("firstName", "lastName"); + + insert(); + + WriteResult result = collection.remove(and(where("firstName").eq("fn1"), + where("lastName").eq("ln1"))); + assertEquals(result.getAffectedCount(), 1); + + result = collection.remove(and(where("firstName").eq("fn2"), + where("birthDay").gte(new Date()))); + assertEquals(result.getAffectedCount(), 0); + } + + @Test + public void testRebuildIndexOnRunningIndex() { + insert(); + db.getStore().subscribe(System.out::println); + + collection.createIndex("firstName", "lastName"); + collection.rebuildIndex("firstName", "lastName"); + + assertTrue(collection.hasIndex("firstName", "lastName")); + } + + @Test + public void testNullValuesInIndexedFields() { + collection.createIndex("firstName", "lastName"); + collection.createIndex("birthDay", "lastName"); + Document document = createDocument("firstName", null) + .put("lastName", "ln1") + .put("birthDay", new Date()) + .put("data", new byte[]{1, 2, 3}) + .put("list", new ArrayList() {{ + add("one"); + add("two"); + add("three"); + }}) + .put("body", "a quick brown fox jump over the lazy dog"); + + insert(); + collection.insert(document); + + DocumentCursor cursor = collection.find(where("fistName").eq(null)); + assertEquals("ln1", cursor.firstOrNull().get("lastName", String.class)); + assertNull(cursor.firstOrNull().get("fistName", String.class)); + + document = createDocument("firstName", "fn4") + .put("lastName", null) + .put("birthDay", null) + .put("data", new byte[]{1, 2, 3}) + .put("list", new ArrayList() {{ + add("one"); + add("two"); + add("three"); + }}) + .put("body", "a quick brown fox jump over the lazy dog"); + collection.insert(document); + + cursor = collection.find(where("lastName").eq(null)); + assertEquals("fn4", cursor.firstOrNull().get("firstName", String.class)); + assertNull(cursor.firstOrNull().get("fistName", String.class)); + + cursor = collection.find(and(where("lastName").eq(null), where("birthDay").eq(null))); + assertNull(cursor.firstOrNull().get("lastName", String.class)); + } + + @Test + public void testDropAllAndCreateIndex() { + collection.createIndex("firstName", "lastName"); + assertTrue(collection.hasIndex("firstName")); + + DocumentCursor cursor = collection.find(and(where("firstName").eq("fn1"), + where("lastName").eq("ln1"))); + FindPlan findPlan = cursor.getFindPlan(); + assertNotNull(findPlan.getIndexScanFilter()); + assertNull(findPlan.getCollectionScanFilter()); + + collection.dropAllIndices(); + cursor = collection.find(and(where("firstName").eq("fn1"), + where("lastName").eq("ln1"))); + findPlan = cursor.getFindPlan(); + assertNull(findPlan.getIndexScanFilter()); + assertNotNull(findPlan.getCollectionScanFilter()); + + collection.createIndex("firstName", "lastName"); + cursor = collection.find(and(where("firstName").eq("fn1"), + where("lastName").eq("ln1"))); + findPlan = cursor.getFindPlan(); + assertNotNull(findPlan.getIndexScanFilter()); + assertNull(findPlan.getCollectionScanFilter()); + } + + @Test + public void testIssue178() { + collection.dropAllIndices(); + collection.remove(Filter.ALL); + + Document doc1 = createDocument("field1", 5); + Document doc2 = createDocument("field1", 4.3).put("field2", 3.5); + Document doc3 = createDocument("field1", 0.03).put("field2", 5); + Document doc4 = createDocument("field1", 4).put("field2", 4.5); + Document doc5 = createDocument("field1", 5.0).put("field2", 5.0); + + collection.insert(doc1, doc2, doc3, doc4, doc5); + + DocumentCursor cursor = collection.find(and(where("field1").eq(0.03), + where("field2").eq(5))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(and(where("field1").eq(5), + where("field2").eq(null))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("field1").eq(5)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("field1").eq(5.0)); + assertEquals(cursor.size(), 1); + + collection.createIndex("field1", "field2"); + cursor = collection.find(and(where("field1").eq(0.03), + where("field2").eq(5))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(and(where("field1").eq(5), + where("field2").eq(null))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("field1").eq(5)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("field1").eq(5.0)); + assertEquals(cursor.size(), 1); + } + + @Test + public void testIndexEvent() { + NitriteCollection collection = db.getCollection("index-test"); + Random random = new Random(); + for (int i = 0; i < 10000; i++) { + Document document = createDocument("first", random.nextInt()) + .put("second", random.nextDouble()); + collection.insert(document); + } + + AtomicBoolean failed = new AtomicBoolean(false); + AtomicBoolean completed = new AtomicBoolean(false); + collection.subscribe(eventInfo -> { + switch (eventInfo.getEventType()) { + case Insert: + case Remove: + case Update: + failed.set(true); + break; + case IndexStart: + case IndexEnd: + completed.set(true); + break; + } + }); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "first", "second"); + assertEquals(collection.find().size(), 10000); + + await().until(completed::get); + assertFalse(failed.get()); + } + + @Test + public void testIndexAndSearchOnNullValues() { + NitriteCollection collection = db.getCollection("index-on-null"); + collection.insert(createDocument("first", null).put("second", 123).put("third", new Integer[]{1, 2, null})); + collection.insert(createDocument("first", "abcd").put("second", 456).put("third", new int[]{3, 1})); + collection.insert(createDocument("first", "xyz").put("second", 789).put("third", null)); + + collection.createIndex("third", "first"); + assertEquals(collection.find(where("first").eq(null)).size(), 1); + + assertEquals(collection.find(where("third").eq(null)).size(), 2); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionDeleteNegativeTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionDeleteNegativeTest.java new file mode 100644 index 000000000..9c9d9bd6a --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionDeleteNegativeTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.exceptions.NitriteIOException; +import org.dizitart.no2.exceptions.ValidationException; +import org.junit.Test; + +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionDeleteNegativeTest extends BaseCollectionTest { + @Test(expected = NitriteIOException.class) + public void testDrop() { + collection.drop(); + insert(); + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + } + + @Test(expected = FilterException.class) + public void testDeleteWithInvalidFilter() { + insert(); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + + WriteResult writeResult = collection.remove(where("lastName").gt(null)); + assertEquals(writeResult.getAffectedCount(), 0); + } + + @Test(expected = ValidationException.class) + public void testDeleteNullDocument() { + insert(); + + collection.remove((Document) null); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionDeleteTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionDeleteTest.java new file mode 100644 index 000000000..ca1660599 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionDeleteTest.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class CollectionDeleteTest extends BaseCollectionTest { + + @Test + public void testDelete() { + insert(); + + WriteResult writeResult = collection.remove(where("lastName").notEq(null)); + assertEquals(writeResult.getAffectedCount(), 3); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 0); + } + + @Test + public void testDeleteWithOptions() { + insert(); + + WriteResult writeResult = collection.remove(where("lastName").notEq(null), true); + assertEquals(writeResult.getAffectedCount(), 1); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 2); + } + + @Test + public void testDeleteWithNonMatchingFilter() { + insert(); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + + WriteResult writeResult = collection.remove(where("lastName").eq("a")); + assertEquals(writeResult.getAffectedCount(), 0); + } + + @Test + public void testDeleteInEmptyCollection() { + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 0); + + WriteResult writeResult = collection.remove(where("lastName").notEq(null)); + assertEquals(writeResult.getAffectedCount(), 0); + } + + @Test + public void testClear() { + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "firstName"); + insert(); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + assertTrue(collection.hasIndex("firstName")); + + boolean uniqueError = false; + try { + collection.insert(doc1); + } catch (Exception e) { + uniqueError = true; + } finally { + assertTrue(uniqueError); + } + + collection.remove(Filter.ALL); + + cursor = collection.find(); + assertEquals(cursor.size(), 0); + assertTrue(collection.hasIndex("firstName")); + + collection.insert(doc1); + cursor = collection.find(); + assertEquals(cursor.size(), 1); + assertTrue(collection.hasIndex("firstName")); + } + + @Test + public void testRemoveAll() { + insert(); + WriteResult writeResult = collection.remove((Filter) null); + assertEquals(writeResult.getAffectedCount(), 3); + } + + @Test + public void testRemoveDocument() { + insert(); + + WriteResult writeResult = collection.remove(where("firstName").eq("fn1")); + assertEquals(writeResult.getAffectedCount(), 1); + assertEquals(collection.size(), 2); + + writeResult = collection.remove(where("firstName").eq("fn2")); + assertEquals(writeResult.getAffectedCount(), 1); + assertEquals(collection.size(), 1); + + assertEquals(collection.find(where("firstName").eq("fn1")).size(), 0); + assertEquals(collection.find(where("firstName").eq("fn2")).size(), 0); + assertEquals(collection.find(where("firstName").eq("fn3")).size(), 1); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionFieldIndexTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionFieldIndexTest.java new file mode 100644 index 000000000..15fe879b5 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionFieldIndexTest.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.integration.Retry; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import static org.dizitart.no2.integration.TestUtil.createDb; +import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee + */ +public class CollectionFieldIndexTest { + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + db = createDb(); + } + + @Test + public void testCollection() { + Document doc1 = Document.createDocument("name", "Anindya") + .put("color", new String[]{"red", "green", "blue"}) + .put("books", new Document[]{ + Document.createDocument("name", "Book ABCD") + .put("tag", new String[]{"tag1", "tag2"}), + Document.createDocument("name", "Book EFGH") + .put("tag", new String[]{"tag3", "tag1"}), + Document.createDocument("name", "No Tag") + }); + + Document doc2 = Document.createDocument("name", "Bill") + .put("color", new String[]{"purple", "yellow", "gray"}) + .put("books", new Document[]{ + Document.createDocument("name", "Book abcd") + .put("tag", new String[]{"tag4", "tag5"}), + Document.createDocument("name", "Book wxyz") + .put("tag", new String[]{"tag3", "tag1"}), + Document.createDocument("name", "No Tag 2") + }); + + Document doc3 = Document.createDocument("name", "John") + .put("color", new String[]{"black", "sky", "violet"}) + .put("books", new Document[]{ + Document.createDocument("name", "Book Mnop") + .put("tag", new String[]{"tag6", "tag2"}), + Document.createDocument("name", "Book ghij") + .put("tag", new String[]{"tag3", "tag7"}), + Document.createDocument("name", "No Tag") + }); + + NitriteCollection collection = db.getCollection("test"); + collection.createIndex("color"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "books.tag"); + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "books.name"); + + WriteResult writeResult = collection.insert(doc1, doc2, doc3); + assertEquals(writeResult.getAffectedCount(), 3); + + DocumentCursor documents = collection.find(where("color").eq("red")); + assertTrue(isSimilar(documents.firstOrNull(), doc1, "name", "color", "books")); + + documents = collection.find(where("books.name").text("abcd")); + assertEquals(documents.size(), 2); + + documents = collection.find(where("books.tag").eq("tag2")); + assertEquals(documents.size(), 2); + + documents = collection.find(where("books.tag").eq("tag5")); + assertEquals(documents.size(), 1); + + documents = collection.find(where("books.tag").eq("tag10")); + assertEquals(documents.size(), 0); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionFindByCompoundIndexTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionFindByCompoundIndexTest.java new file mode 100644 index 000000000..8fd30693e --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionFindByCompoundIndexTest.java @@ -0,0 +1,503 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.FindPlan; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.filters.AndFilter; +import org.dizitart.no2.filters.IndexScanFilter; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import java.text.ParseException; +import java.util.List; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.collection.FindOptions.orderBy; +import static org.dizitart.no2.filters.Filter.and; +import static org.dizitart.no2.filters.Filter.or; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class CollectionFindByCompoundIndexTest extends BaseCollectionTest { + + @Test + public void testFindByAndFilter() { + insert(); + collection.createIndex("list", "lastName", "firstName"); + DocumentCursor cursor = collection.find(and( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1"), + where("list").eq("four") + )); + + FindPlan findPlan = cursor.getFindPlan(); + assertNull(findPlan.getCollectionScanFilter()); + assertNotNull(findPlan.getIndexDescriptor()); + assertEquals(findPlan.getIndexDescriptor(), collection.listIndices().toArray()[0]); + + IndexScanFilter indexScanFilter = findPlan.getIndexScanFilter(); + assertEquals(indexScanFilter.getFilters().get(0), where("list").eq("four")); + assertEquals(indexScanFilter.getFilters().get(1), where("lastName").eq("ln2")); + assertEquals(indexScanFilter.getFilters().get(2), where("firstName").notEq("fn1")); + + List documents = cursor.toList(); + assertEquals(documents.size(), 1); + assertEquals(documents.get(0).get("body", String.class), "quick hello world from nitrite"); + } + + @Test + public void testFindByOrFilterAndFilter() { + insert(); + collection.createIndex("lastName", "firstName"); + DocumentCursor cursor = collection.find( + or( + and( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + ), + and( + where("firstName").eq("fn3"), + where("lastName").eq("ln2") + ) + ) + ); + + assertEquals(2, cursor.size()); + + FindPlan findPlan = cursor.getFindPlan(); + assertNull(findPlan.getIndexScanFilter()); + assertNull(findPlan.getCollectionScanFilter()); + assertNotNull(findPlan.getSubPlans()); + + assertEquals(2, findPlan.getSubPlans().size()); + assertNotNull(findPlan.getSubPlans().get(0).getIndexScanFilter()); + assertNotNull(findPlan.getSubPlans().get(1).getIndexScanFilter()); + + assertEquals(1, cursor.toList().stream().filter(d -> + d.get("firstName", String.class).equals("fn2") + && d.get("lastName", String.class).equals("ln2")).count()); + + assertEquals(1, cursor.toList().stream().filter(d -> + d.get("firstName", String.class).equals("fn3") + && d.get("lastName", String.class).equals("ln2")).count()); + } + + @Test + public void testFindByAndFilterOrFilter() { + insert(); + collection.createIndex("lastName", "firstName"); + DocumentCursor cursor = collection.find( + and( + or( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + ), + or( + where("firstName").eq("fn3"), + where("lastName").eq("ln2") + ) + ) + ); + + assertEquals(2, cursor.size()); + + FindPlan findPlan = cursor.getFindPlan(); + assertNull(findPlan.getIndexScanFilter()); + assertNotNull(findPlan.getCollectionScanFilter()); + assertTrue(findPlan.getSubPlans().isEmpty()); + + assertEquals(and( + or( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + ), + or( + where("firstName").eq("fn3"), + where("lastName").eq("ln2") + ) + ), findPlan.getCollectionScanFilter()); + } + + @Test + public void testFindByAndFilterAndFilter() { + insert(); + collection.createIndex("lastName", "firstName"); + DocumentCursor cursor = collection.find( + and( + and( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + ), + and( + where("firstName").eq("fn3"), + where("lastName").eq("ln2") + ) + ) + ); + + assertEquals(1, cursor.size()); + FindPlan findPlan = cursor.getFindPlan(); + + assertNotNull(findPlan.getIndexDescriptor()); + assertEquals(collection.listIndices().toArray()[0], findPlan.getIndexDescriptor()); + + assertNotNull(findPlan.getIndexScanFilter()); + assertEquals(findPlan.getIndexScanFilter().getFilters(), + ((AndFilter) and( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + )).getFilters()); + + assertNotNull(findPlan.getCollectionScanFilter()); + assertEquals(where("firstName").eq("fn3"), findPlan.getCollectionScanFilter()); + + assertTrue(findPlan.getSubPlans().isEmpty()); + + assertEquals(cursor.toList().get(0).get("firstName", String.class), "fn3"); + } + + @Test + public void testFindByOrFilter() throws ParseException { + // all or clause has index + insert(); + collection.createIndex("lastName", "firstName"); + collection.createIndex("firstName"); + collection.createIndex("birthDay"); + DocumentCursor cursor = collection.find( + or( + or( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + ), + where("birthDay").eq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")), + where("firstName").notEq("fn1") + ) + ); + + FindPlan findPlan = cursor.getFindPlan(); + assertEquals(3, findPlan.getSubPlans().size()); + assertEquals(3, cursor.size()); + } + + @Test + public void testFindOrNoIndex() throws ParseException { + // on of the or clause has no index + insert(); + collection.createIndex("lastName", "firstName"); + collection.createIndex("firstName"); + DocumentCursor cursor = collection.find( + or( + or( + where("lastName").eq("ln2"), + where("firstName").notEq("fn1") + ), + where("birthDay").eq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")), + where("firstName").notEq("fn1") + ) + ); + + FindPlan findPlan = cursor.getFindPlan(); + assertEquals(0, findPlan.getSubPlans().size()); + assertEquals(3, cursor.size()); + } + + @Test + public void testFindAndNoIndex() throws ParseException { + // index at second field + insert(); + collection.createIndex("lastName", "firstName"); + DocumentCursor cursor = collection.find( + and( + where("firstName").notEq("fn1"), + where("birthDay").eq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + ) + ); + + FindPlan findPlan = cursor.getFindPlan(); + assertNull(findPlan.getIndexScanFilter()); + assertNull(findPlan.getIndexDescriptor()); + + assertNotNull(findPlan.getCollectionScanFilter()); + assertEquals(0, cursor.size()); + } + + @Test + public void testSortByIndex() throws ParseException { + // multiple field sort in both direction + collection.createIndex("lastName", "birthDay"); + + Document doc = createDocument("firstName", "fn4") + .put("lastName", "ln3") + .put("birthDay", simpleDateFormat.parse("2016-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + collection.insert(doc); + collection.insert(doc3); + collection.insert(doc1); + collection.insert(doc2); + + DocumentCursor cursor = collection.find( + and( + where("lastName").notEq("ln1"), + where("birthDay").notEq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + ), + orderBy("lastName", SortOrder.Ascending) + .thenOrderBy("birthDay", SortOrder.Descending) + ); + + List documents = cursor.toList(); + assertEquals(3, documents.size()); + + Document document = documents.get(0); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2014-04-17T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(1); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2010-06-12T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(2); + assertEquals("ln3", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2016-04-17T16:02:48.440Z"), document.get("birthDay")); + + FindPlan findPlan = cursor.getFindPlan(); + assertTrue(findPlan.getBlockingSortOrder().isEmpty()); + assertNull(findPlan.getCollectionScanFilter()); + assertNotNull(findPlan.getIndexDescriptor()); + assertFalse(findPlan.getIndexScanOrder().get("lastName")); + + // reverse scan + assertTrue(findPlan.getIndexScanOrder().get("birthDay")); + } + + @Test + public void testBlockingSort() throws ParseException { + // multiple field sort in memory + + Document doc = createDocument("firstName", "fn4") + .put("lastName", "ln3") + .put("birthDay", simpleDateFormat.parse("2016-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + collection.insert(doc); + collection.insert(doc3); + collection.insert(doc1); + collection.insert(doc2); + + DocumentCursor cursor = collection.find( + and( + where("lastName").notEq("ln1"), + where("birthDay").notEq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + ), + orderBy("lastName", SortOrder.Ascending) + .thenOrderBy("birthDay", SortOrder.Descending) + ); + + List documents = cursor.toList(); + assertEquals(3, documents.size()); + + Document document = documents.get(0); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2014-04-17T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(1); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2010-06-12T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(2); + assertEquals("ln3", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2016-04-17T16:02:48.440Z"), document.get("birthDay")); + + FindPlan findPlan = cursor.getFindPlan(); + List> blockingSortOrder = findPlan.getBlockingSortOrder(); + assertEquals(2, blockingSortOrder.size()); + + Pair pair = blockingSortOrder.get(0); + assertEquals("lastName", pair.getFirst()); + assertEquals(SortOrder.Ascending, pair.getSecond()); + + pair = blockingSortOrder.get(1); + assertEquals("birthDay", pair.getFirst()); + assertEquals(SortOrder.Descending, pair.getSecond()); + + assertNotNull(findPlan.getCollectionScanFilter()); + assertNull(findPlan.getIndexDescriptor()); + assertNull(findPlan.getIndexScanOrder()); + } + + @Test + public void testSortNotCoveredByIndex() throws ParseException { + // some field sort by index, some by memory + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + + Document doc = createDocument("firstName", "fn4") + .put("lastName", "ln3") + .put("birthDay", simpleDateFormat.parse("2016-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + collection.insert(doc); + collection.insert(doc3); + collection.insert(doc1); + collection.insert(doc2); + + DocumentCursor cursor = collection.find( + and( + where("lastName").notEq("ln1"), + where("birthDay").notEq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + ), + orderBy("lastName", SortOrder.Ascending) + .thenOrderBy("birthDay", SortOrder.Descending) + ); + + List documents = cursor.toList(); + assertEquals(3, documents.size()); + + Document document = documents.get(0); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2014-04-17T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(1); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2010-06-12T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(2); + assertEquals("ln3", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2016-04-17T16:02:48.440Z"), document.get("birthDay")); + + FindPlan findPlan = cursor.getFindPlan(); + List> blockingSortOrder = findPlan.getBlockingSortOrder(); + assertEquals(2, blockingSortOrder.size()); + + Pair pair = blockingSortOrder.get(0); + assertEquals("lastName", pair.getFirst()); + assertEquals(SortOrder.Ascending, pair.getSecond()); + + pair = blockingSortOrder.get(1); + assertEquals("birthDay", pair.getFirst()); + assertEquals(SortOrder.Descending, pair.getSecond()); + + assertNotNull(findPlan.getCollectionScanFilter()); + assertNotNull(findPlan.getIndexDescriptor()); + assertNull(findPlan.getIndexScanOrder()); + } + + @Test + public void testSortByIndexPrefix() throws ParseException { + collection.createIndex("lastName", "birthDay"); + + Document doc = createDocument("firstName", "fn4") + .put("lastName", "ln3") + .put("birthDay", simpleDateFormat.parse("2016-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + collection.insert(doc); + collection.insert(doc3); + collection.insert(doc1); + collection.insert(doc2); + + DocumentCursor cursor = collection.find( + and( + where("lastName").notEq("ln1"), + where("birthDay").notEq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + ), + orderBy("lastName", SortOrder.Ascending) + ); + + List documents = cursor.toList(); + assertEquals(3, documents.size()); + + Document document = documents.get(0); + assertEquals("ln2", document.get("lastName")); + // duplicate birthday will have natural sort order - ascending + assertEquals(simpleDateFormat.parse("2010-06-12T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(1); + assertEquals("ln2", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2014-04-17T16:02:48.440Z"), document.get("birthDay")); + + document = documents.get(2); + assertEquals("ln3", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2016-04-17T16:02:48.440Z"), document.get("birthDay")); + + FindPlan findPlan = cursor.getFindPlan(); + assertTrue(findPlan.getBlockingSortOrder().isEmpty()); + assertNull(findPlan.getCollectionScanFilter()); + assertNotNull(findPlan.getIndexDescriptor()); + assertFalse(findPlan.getIndexScanOrder().get("lastName")); + } + + @Test + public void testLimitAndSkip() throws ParseException { + // test skip and limit + + collection.createIndex("lastName", "birthDay"); + + Document doc = createDocument("firstName", "fn4") + .put("lastName", "ln3") + .put("birthDay", simpleDateFormat.parse("2016-04-17T16:02:48.440Z")) + .put("data", new byte[]{9, 4, 8}) + .put("body", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Sed nunc mi, mattis ullamcorper dignissim vitae, condimentum non lorem."); + collection.insert(doc); + collection.insert(doc3); + collection.insert(doc1); + collection.insert(doc2); + + DocumentCursor cursor = collection.find( + and( + where("lastName").notEq("ln1"), + where("birthDay").notEq(simpleDateFormat.parse("2012-07-01T16:02:48.440Z")) + ), + orderBy("lastName", SortOrder.Ascending) + .thenOrderBy("birthDay", SortOrder.Descending) + .skip(2) + .limit(1) + ); + + List documents = cursor.toList(); + assertEquals(1, documents.size()); + + Document document = documents.get(0); + assertEquals("ln3", document.get("lastName")); + assertEquals(simpleDateFormat.parse("2016-04-17T16:02:48.440Z"), document.get("birthDay")); + + FindPlan findPlan = cursor.getFindPlan(); + assertTrue(findPlan.getBlockingSortOrder().isEmpty()); + assertNull(findPlan.getCollectionScanFilter()); + assertNotNull(findPlan.getIndexDescriptor()); + assertFalse(findPlan.getIndexScanOrder().get("lastName")); + assertEquals(2L, (long)findPlan.getSkip()); + assertEquals(1L, (long)findPlan.getLimit()); + + // reverse scan + assertTrue(findPlan.getIndexScanOrder().get("birthDay")); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionFindByIndexNegativeTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionFindByIndexNegativeTest.java new file mode 100644 index 000000000..76b84a0e6 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionFindByIndexNegativeTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionFindByIndexNegativeTest extends BaseCollectionTest { + @Test(expected = FilterException.class) + public void testFindTextWithWildCardMultipleWord() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + + DocumentCursor cursor = collection.find(where("body").text("*ipsum dolor*")); + assertEquals(cursor.size(), 1); + } + + @Test(expected = FilterException.class) + public void testFindTextWithOnlyWildCard() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + + DocumentCursor cursor = collection.find(where("body").text("*")); + assertEquals(cursor.size(), 1); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionFindBySingleFieldIndexTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionFindBySingleFieldIndexTest.java new file mode 100644 index 000000000..cbef67e26 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionFindBySingleFieldIndexTest.java @@ -0,0 +1,423 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import com.github.javafaker.Faker; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import static org.dizitart.no2.integration.TestUtil.isSorted; +import static org.dizitart.no2.collection.FindOptions.orderBy; +import static org.dizitart.no2.filters.Filter.and; +import static org.dizitart.no2.filters.Filter.or; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionFindBySingleFieldIndexTest extends BaseCollectionTest { + + @Test + public void testFindByUniqueIndex() throws ParseException { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "firstName"); + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("firstName").eq("fn10")); + assertEquals(cursor.size(), 0); + + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "birthDay"); + cursor = collection.find(where("birthDay").gt( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").gte( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lt( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").lte( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lte( + new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").lt( + new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").gt( + new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("birthDay").gte( + new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find( + where("birthDay").lte(new Date()) + .and(where("firstName").eq("fn1"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + where("birthDay").lte(new Date()) + .or(where("firstName").eq("fn12"))); + assertEquals(cursor.size(), 3); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + )); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + ).not()); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").eq((byte) 4)); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").lt(4)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("firstName").notIn("fn1", "fn2")); + assertEquals(cursor.size(), 1); + } + + @Test + public void testFindByNonUniqueIndex() throws ParseException { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "lastName"); + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "birthDay"); + + DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("lastName").eq("ln20")); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("birthDay").gt( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").gte( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lt( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").lte( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lte( + new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").lt( + new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").gt( + new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("birthDay").gte( + new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find( + where("birthDay").lte(new Date()) + .and(where("firstName").eq("fn1"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + where("birthDay").lte(new Date()) + .or(where("firstName").eq("fn12"))); + assertEquals(cursor.size(), 3); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + )); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + ).not()); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").eq((byte) 4)); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").lt(4)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("firstName").notIn("fn1", "fn2")); + assertEquals(cursor.size(), 1); + } + + @Test + public void testFindByFullTextIndexAfterInsert() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + + DocumentCursor cursor = collection.find(where("body").text("Lorem")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("body").text("nosql")); + assertEquals(cursor.size(), 0); + + collection.dropIndex("body"); + boolean filterException = false; + try { + collection.find(where("body").text("Lorem")).toList(); + } catch (FilterException fe) { + filterException = true; + } finally { + assertTrue(filterException); + } + } + + @Test + public void testFindByFullTextIndexBeforeInsert() { + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + insert(); + + DocumentCursor cursor = collection.find(where("body").text("Lorem")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("body").text("quick brown")); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("body").text("nosql")); + assertEquals(cursor.size(), 0); + + collection.dropIndex("body"); + boolean filterException = false; + try { + collection.find(where("body").text("Lorem")).toList(); + } catch (FilterException fe) { + filterException = true; + } finally { + assertTrue(filterException); + } + } + + @Test + public void testFindByIndexSortAscending() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "birthDay"); + + DocumentCursor cursor = collection.find(orderBy("birthDay", SortOrder.Ascending)); + assertEquals(cursor.size(), 3); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, true)); + } + + @Test + public void testFindByIndexSortDescending() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "birthDay"); + + DocumentCursor cursor = collection.find(orderBy("birthDay", SortOrder.Descending)); + assertEquals(cursor.size(), 3); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, false)); + } + + @Test + public void testFindByIndexLimitAndSort() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "birthDay"); + + DocumentCursor cursor = collection.find( + orderBy("birthDay", SortOrder.Descending) + .skip(1) + .limit(2) + ); + assertEquals(cursor.size(), 2); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, false)); + + cursor = collection.find(orderBy("birthDay", SortOrder.Ascending).skip(1).limit(2)); + assertEquals(cursor.size(), 2); + dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, true)); + + cursor = collection.find(orderBy("firstName", SortOrder.Ascending).skip(0).limit(30)); + assertEquals(cursor.size(), 3); + List nameList = new ArrayList<>(); + for (Document document : cursor) { + nameList.add(document.get("firstName", String.class)); + } + assertTrue(isSorted(nameList, true)); + } + + @Test + public void testFindAfterDroppedIndex() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "firstName"); + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + + collection.dropIndex("firstName"); + cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + } + + @Test + public void testFindTextWithWildCard() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + + DocumentCursor cursor = collection.find(where("body").text("Lo")); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("body").text("Lo*")); + assertEquals(cursor.size(), 1); // Lorem + + cursor = collection.find(where("body").text("*rem")); + assertEquals(cursor.size(), 1); // lorem + + cursor = collection.find(where("body").text("*or*")); + assertEquals(cursor.size(), 2); + } + + @Test + public void testFindTextWithEmptyString() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "body"); + + DocumentCursor cursor = collection.find(where("body").text("")); + assertEquals(cursor.size(), 0); + } + + @Test + public void testFindWithOrIndexed() { + NitriteCollection collection = db.getCollection("testFindWithOrIndexed"); + Document doc1 = Document.createDocument("firstName", "John").put("lastName", "Doe"); + Document doc2 = Document.createDocument("firstName", "Jane").put("lastName", "Doe"); + Document doc3 = Document.createDocument("firstName", "Jonas").put("lastName", "Doe"); + Document doc4 = Document.createDocument("firstName", "Johan").put("lastName", "Day"); + + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "firstName"); + collection.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "lastName"); + + collection.insert(doc1, doc2, doc3, doc4); + + DocumentCursor cursor = collection.find(where("firstName").eq("John").or(where("lastName").eq("Day"))); + assertEquals(cursor.size(), 2); + + List list = cursor.toList(); + assertEquals(list.size(), 2); + } + + @Test + public void testIssue45() { + NitriteCollection collection = db.getCollection("testIssue45"); + Faker faker = new Faker(); + String text1 = faker.lorem().paragraph() + " quick brown"; + String text2 = faker.lorem().paragraph() + " fox jump"; + String text3 = faker.lorem().paragraph() + " over lazy"; + String text4 = faker.lorem().paragraph() + " dog"; + + List list1 = Arrays.asList(text1, text2); + List list2 = Arrays.asList(text1, text2, text3); + List list3 = Arrays.asList(text2, text3); + List list4 = Arrays.asList(text1, text2, text3, text4); + + Document doc1 = Document.createDocument("firstName", "John").put("notes", list1); + Document doc2 = Document.createDocument("firstName", "Jane").put("notes", list2); + Document doc3 = Document.createDocument("firstName", "Jonas").put("notes", list3); + Document doc4 = Document.createDocument("firstName", "Johan").put("notes", list4); + + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "notes"); + collection.insert(doc1, doc2, doc3, doc4); + + DocumentCursor cursor = collection.find(where("notes").text("fox")); + assertEquals(cursor.size(), 4); + + cursor = collection.find(where("notes").text("dog")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("notes").text("lazy")); + assertEquals(cursor.size(), 3); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionFindNegativeTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionFindNegativeTest.java new file mode 100644 index 000000000..c0e84a688 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionFindNegativeTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.exceptions.ValidationException; +import org.junit.Test; + +import java.util.Date; +import java.util.List; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.collection.FindOptions.orderBy; +import static org.dizitart.no2.collection.FindOptions.skipBy; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionFindNegativeTest extends BaseCollectionTest { + @Test(expected = ValidationException.class) + public void testFindFilterInvalidIndex() { + insert(); + collection.find(where("data.9").eq(4)).toList(); + } + + @Test(expected = ValidationException.class) + public void testFindOptionsNegativeOffset() { + insert(); + collection.find(skipBy(-1).limit(1)); + } + + @Test(expected = ValidationException.class) + public void testFindOptionsNegativeSize() { + insert(); + collection.find(skipBy(0).limit(-1)); + } + + @Test(expected = ValidationException.class) + public void testFindInvalidSort() { + insert(); + collection.find(orderBy("data", SortOrder.Descending)).toList(); + } + + @Test(expected = FilterException.class) + public void testFindTextFilterNonIndexed() { + insert(); + collection.find(where("body").text("Lorem")).toList(); + } + + @Test(expected = FilterException.class) + public void testFindWithRegexInvalidValue() { + insert(); + DocumentCursor cursor = collection.find(where("birthDay").regex("hello")); + assertEquals(cursor.size(), 1); + } + + @Test(expected = ValidationException.class) + public void testInvalidProjection() { + insert(); + DocumentCursor cursor = collection.find(where("birthDay").lte(new Date()), + orderBy("firstName", SortOrder.Ascending).skip(0).limit(3)); + + Document projection = createDocument("firstName", null) + .put("lastName", "ln2"); + + cursor.project(projection); + } + + @Test(expected = UnsupportedOperationException.class) + public void testToListAdd() { + insert(); + DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); + List documents = cursor.toList(); + documents.add(createDocument()); + } + + @Test(expected = UnsupportedOperationException.class) + public void testToListRemove() { + insert(); + DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); + List documents = cursor.toList(); + documents.clear(); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionFindTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionFindTest.java new file mode 100644 index 000000000..25061010c --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionFindTest.java @@ -0,0 +1,809 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.joda.time.DateTime; +import org.junit.Test; + +import java.text.Collator; +import java.text.ParseException; +import java.util.*; +import java.util.stream.Collectors; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.collection.FindOptions.*; +import static org.dizitart.no2.common.Constants.*; +import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; +import static org.dizitart.no2.filters.Filter.*; +import static org.dizitart.no2.filters.FluentFilter.$; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.integration.TestUtil.isSorted; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.*; + +public class CollectionFindTest extends BaseCollectionTest { + + private static Document trimMeta(Document document) { + document.remove(DOC_ID); + document.remove(DOC_REVISION); + document.remove(DOC_MODIFIED); + document.remove(DOC_SOURCE); + return document; + } + + @Test + public void testFindAll() { + insert(); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + } + + @Test + public void testFindWithFilter() throws ParseException { + insert(); + + DocumentCursor cursor = collection.find(where("birthDay").gt( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").gte( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lt( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("birthDay").lte( + simpleDateFormat.parse("2012-07-01T16:02:48.440Z"))); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("birthDay").lte( + new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").lt( + new Date())); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("birthDay").gt( + new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("birthDay").gte( + new Date())); + assertEquals(cursor.size(), 0); + + cursor = collection.find( + where("birthDay").lte(new Date()) + .and(where("firstName").eq("fn1"))); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + where("birthDay").lte(new Date()) + .or(where("firstName").eq("fn12"))); + assertEquals(cursor.size(), 3); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + )); + assertEquals(cursor.size(), 1); + + cursor = collection.find( + and( + or( + where("birthDay").lte(new Date()), + where("firstName").eq("fn12") + ), + where("lastName").eq("ln1") + ).not()); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").eq((byte) 4)); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("data.1").lt(4)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("lastName").in("ln1", "ln2", "ln10")); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("firstName").notIn("fn1", "fn2")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(ALL.not()); + assertEquals(cursor.size(), 0); + } + + @Test + public void testFindWithSkipLimit() { + insert(); + + DocumentCursor cursor = collection.find(skipBy(0).limit(1)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(skipBy(1).limit(3)); + assertEquals(cursor.size(), 2); + + cursor = collection.find(skipBy(0).limit(30)); + assertEquals(cursor.size(), 3); + + cursor = collection.find(skipBy(2).limit(3)); + assertEquals(cursor.size(), 1); + } + + @Test + public void testFindWithSkip() { + insert(); + + DocumentCursor cursor = collection.find(skipBy(0)); + assertEquals(cursor.size(), 3); + + cursor = collection.find(skipBy(1)); + assertEquals(cursor.size(), 2); + + cursor = collection.find(skipBy(30)); + assertEquals(cursor.size(), 0); + + cursor = collection.find(skipBy(2)); + assertEquals(cursor.size(), 1); + + boolean invalid = false; + try { + cursor = collection.find(skipBy(-1)); + assertEquals(cursor.size(), 1); + } catch (ValidationException e) { + invalid = true; + } + assertTrue(invalid); + } + + @Test + public void testFindWithLimit() { + insert(); + + DocumentCursor cursor = collection.find(limitBy(0)); + assertEquals(cursor.size(), 0); + + cursor = collection.find(limitBy(1)); + assertEquals(cursor.size(), 1); + + boolean invalid = false; + try { + cursor = collection.find(limitBy(-1)); + assertEquals(cursor.size(), 1); + } catch (ValidationException e) { + invalid = true; + } + assertTrue(invalid); + + cursor = collection.find(limitBy(30)); + assertEquals(cursor.size(), 3); + } + + @Test + public void testFindSortAscending() { + insert(); + + DocumentCursor cursor = collection.find(orderBy("birthDay", SortOrder.Ascending)); + assertEquals(cursor.size(), 3); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, true)); + } + + @Test + public void testFindSortDescending() { + insert(); + + DocumentCursor cursor = collection.find(orderBy("birthDay", SortOrder.Descending)); + assertEquals(cursor.size(), 3); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, false)); + } + + @Test + public void testFindLimitAndSort() { + insert(); + + DocumentCursor cursor = collection.find(orderBy("birthDay", SortOrder.Descending).skip(1).limit(2)); + assertEquals(cursor.size(), 2); + List dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, false)); + + cursor = collection.find(orderBy("birthDay", SortOrder.Ascending).skip(1).limit(2)); + assertEquals(cursor.size(), 2); + dateList = new ArrayList<>(); + for (Document document : cursor) { + dateList.add(document.get("birthDay", Date.class)); + } + assertTrue(isSorted(dateList, true)); + + cursor = collection.find(orderBy("firstName", SortOrder.Ascending).skip(0).limit(30)); + assertEquals(cursor.size(), 3); + List nameList = new ArrayList<>(); + for (Document document : cursor) { + nameList.add(document.get("firstName", String.class)); + } + assertTrue(isSorted(nameList, true)); + } + + @Test + public void testFindSortOnNonExistingField() { + insert(); + DocumentCursor cursor = collection.find(orderBy("my-value", SortOrder.Descending)); + assertEquals(cursor.size(), 3); + } + + @Test + public void testFindInvalidField() { + insert(); + DocumentCursor cursor = collection.find(where("myField").eq("myData")); + assertEquals(cursor.size(), 0); + } + + @Test + public void testFindInvalidFieldWithInvalidAccessor() { + insert(); + DocumentCursor cursor = collection.find(where("myField.0").eq("myData")); + assertEquals(cursor.size(), 0); + } + + @Test + public void testFindLimitAndSortInvalidField() { + insert(); + DocumentCursor cursor = collection.find(orderBy("birthDay2", SortOrder.Descending).skip(1).limit(2)); + assertEquals(cursor.size(), 2); + } + + @Test + public void testGetById() { + collection.insert(doc1); + NitriteId id = NitriteId.createId("1"); + Document document = collection.getById(id); + assertNull(document); + + document = collection.find().firstOrNull(); + + assertEquals(document.get(DOC_ID), document.getId().getIdValue()); + assertEquals(document.get("firstName"), "fn1"); + assertEquals(document.get("lastName"), "ln1"); + assertArrayEquals((byte[]) document.get("data"), new byte[]{1, 2, 3}); + assertEquals(document.get("body"), "a quick brown fox jump over the lazy dog"); + } + + @Test + public void testFindWithFilterAndOption() { + insert(); + DocumentCursor cursor = collection.find(where("birthDay").lte(new Date()), + orderBy("firstName", SortOrder.Ascending).skip(1).limit(2)); + assertEquals(cursor.size(), 2); + } + + @Test + public void testFindTextWithRegex() { + insert(); + DocumentCursor cursor = collection.find(where("body").regex("hello")); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("body").regex("test")); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("body").regex("^hello$")); + assertEquals(cursor.size(), 0); + + cursor = collection.find(where("body").regex(".*")); + assertEquals(cursor.size(), 3); + } + + @Test + public void testProject() { + insert(); + DocumentCursor cursor = collection.find(where("birthDay").lte(new Date()), + orderBy("firstName", SortOrder.Ascending).skip(0).limit(3)); + int iteration = 0; + for (Document document : cursor) { + switch (iteration) { + case 0: + assertTrue(isSimilar(document, doc1, "firstName", "lastName", "birthDay", "data", "list", "body")); + break; + case 1: + assertTrue(isSimilar(document, doc2, "firstName", "lastName", "birthDay", "data", "list", "body")); + break; + case 2: + assertTrue(isSimilar(document, doc3, "firstName", "lastName", "birthDay", "data", "list", "body")); + break; + } + iteration++; + } + assertEquals(iteration, 3); + } + + @Test + public void testProjectWithCustomDocument() { + insert(); + DocumentCursor cursor = collection.find(where("birthDay").lte(new Date()), + orderBy("firstName", SortOrder.Ascending).skip(0).limit(3)); + + Document projection = createDocument("firstName", null) + .put("lastName", null); + + Iterable documents = cursor.project(projection); + int iteration = 0; + for (Document document : documents) { + assertTrue(document.containsKey("firstName")); + assertTrue(document.containsKey("lastName")); + + assertFalse(document.containsKey("_id")); + assertFalse(document.containsKey("birthDay")); + assertFalse(document.containsKey("data")); + assertFalse(document.containsKey("body")); + + switch (iteration) { + case 0: + assertEquals(document.get("firstName"), "fn1"); + assertEquals(document.get("lastName"), "ln1"); + break; + case 1: + assertEquals(document.get("firstName"), "fn2"); + assertEquals(document.get("lastName"), "ln2"); + break; + case 2: + assertEquals(document.get("firstName"), "fn3"); + assertEquals(document.get("lastName"), "ln2"); + break; + } + iteration++; + } + assertEquals(iteration, 3); + } + + @Test + public void testFindWithArrayEqual() { + insert(); + DocumentCursor ids = collection.find(where("data").eq(new byte[]{3, 4, 3})); + assertNotNull(ids); + assertEquals(ids.size(), 1); + } + + @Test + public void testFindWithArrayEqualFailForWrongCardinality() { + insert(); + DocumentCursor ids = collection.find(where("data").eq(new byte[]{4, 3, 3})); + assertNotNull(ids); + assertEquals(ids.size(), 0); + } + + @Test + public void testFindWithIterableEqual() { + insert(); + DocumentCursor ids = collection.find(where("list").eq( + new ArrayList() {{ + add("three"); + add("four"); + add("three"); + }})); + assertNotNull(ids); + assertEquals(ids.size(), 1); + } + + @Test + public void testFindWithIterableEqualFailForWrongCardinality() { + insert(); + DocumentCursor ids = collection.find(where("list").eq( + new ArrayList() {{ + add("four"); + add("three"); + add("three"); + }})); + assertNotNull(ids); + assertEquals(ids.size(), 0); + } + + @Test + public void testFindInArray() { + insert(); + DocumentCursor ids = collection.find(where("data").elemMatch($.gte(2).and($.lt(5)))); + assertNotNull(ids); + assertEquals(ids.size(), 3); + + ids = collection.find(where("data").elemMatch($.gt(2).or($.lte(5)))); + assertNotNull(ids); + assertEquals(ids.size(), 3); + + ids = collection.find(where("data").elemMatch($.gt(1).and($.lt(4)))); + assertNotNull(ids); + assertEquals(ids.size(), 2); + } + + @Test + public void testFindInList() { + insert(); + DocumentCursor ids = collection.find(where("list").elemMatch($.regex("three"))); + assertNotNull(ids); + assertEquals(ids.size(), 2); + + ids = collection.find(where("list").elemMatch($.regex("hello"))); + assertNotNull(ids); + assertEquals(ids.size(), 0); + + ids = collection.find(where("list").elemMatch($.regex("hello").not())); + assertNotNull(ids); + assertEquals(ids.size(), 2); + } + + @Test + public void testElemMatchFilter() { + Document doc1 = createDocument("productScores", new Document[]{ + createDocument("product", "abc").put("score", 10), + createDocument("product", "xyz").put("score", 5) + }).put("strArray", new String[]{"a", "b"}); + + Document doc2 = createDocument("productScores", new Document[]{ + createDocument("product", "abc").put("score", 8), + createDocument("product", "xyz").put("score", 7) + }).put("strArray", new String[]{"d", "e"}); + + Document doc3 = createDocument("productScores", new Document[]{ + createDocument("product", "abc").put("score", 7), + createDocument("product", "xyz").put("score", 8) + }).put("strArray", new String[]{"a", "f"}); + + NitriteCollection prodCollection = db.getCollection("prodScore"); + prodCollection.insert(doc1, doc2, doc3); + + List documentList = prodCollection.find(where("productScores") + .elemMatch(where("product").eq("xyz").and(where("score").gte(8)))).toList(); + + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").lte(8).not())).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("product").eq("xyz").or(where("score").gte(8)))).toList(); + assertEquals(documentList.size(), 3); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("product").eq("xyz"))).toList(); + assertEquals(documentList.size(), 3); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").gte(10))).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").gt(8))).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").lt(7))).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").lte(7))).toList(); + assertEquals(documentList.size(), 3); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").in(7, 8))).toList(); + assertEquals(documentList.size(), 2); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("score").notIn(7, 8))).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("productScores") + .elemMatch(where("product").regex("xyz"))).toList(); + assertEquals(documentList.size(), 3); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.eq("a"))).toList(); + assertEquals(documentList.size(), 2); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.eq("a").or($.eq("f").or($.eq("b"))).not())).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.gt("e"))).toList(); + assertEquals(documentList.size(), 1); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.gte("e"))).toList(); + assertEquals(documentList.size(), 2); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.lte("b"))).toList(); + assertEquals(documentList.size(), 2); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.lt("a"))).toList(); + assertEquals(documentList.size(), 0); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.in("a", "f"))).toList(); + assertEquals(documentList.size(), 2); + + documentList = prodCollection.find(where("strArray") + .elemMatch($.regex("a"))).toList(); + assertEquals(documentList.size(), 2); + + } + + @Test + public void testNotEqualFilter() { + Document document = createDocument("abc", "123"); + document.put("xyz", null); + + collection.insert(document); + DocumentCursor cursor = collection.find(where("abc").eq("123")); + assertEquals(cursor.size(), 1); + assertEquals(cursor.toList().size(), 1); + + cursor = collection.find(where("xyz").eq(null)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("abc").notEq(null)); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("abc").notEq(null).and(where("xyz").eq(null))); + assertEquals(cursor.size(), 1); + + cursor = collection.find(where("abc").eq(null).and(where("xyz").notEq(null))); + assertEquals(cursor.size(), 0); + + collection.remove(ALL); + + document = createDocument("field", "two"); + document.put(DOC_REVISION, 1482225343161L); + + collection.insert(document); + Document projection = collection.find( + where(DOC_REVISION).gte(1482225343160L) + .and(where(DOC_REVISION).lte(1482225343162L) + .and(where(DOC_REVISION).notEq(null)))) + .firstOrNull(); + + assertNull(projection); + } + + @Test + public void testFilterAll() { + DocumentCursor cursor = collection.find(ALL); + assertNotNull(cursor); + assertEquals(cursor.size(), 0); + + insert(); + cursor = collection.find(ALL); + assertNotNull(cursor); + assertEquals(cursor.size(), 3); + } + + @Test + public void testIssue72() { + NitriteCollection coll = db.getCollection("test"); + coll.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "id"); + coll.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "group"); + + coll.remove(ALL); + + Document doc = createDocument().put("id", "test-1").put("group", "groupA"); + assertEquals(1, coll.insert(doc).getAffectedCount()); + + doc = createDocument().put("id", "test-2").put("group", "groupA").put("startTime", DateTime.now()); + assertEquals(1, coll.insert(doc).getAffectedCount()); + + DocumentCursor cursor = coll.find(where("group").eq("groupA"), + orderBy("startTime", SortOrder.Descending)); + assertEquals(2, cursor.size()); + assertNull(cursor.toList().get(1).get("startTime")); + assertNotNull(cursor.toList().get(0).get("startTime")); + + cursor = coll.find(where("group").eq("groupA"), + orderBy("startTime", SortOrder.Ascending)); + assertEquals(2, cursor.size()); + assertNull(cursor.toList().get(0).get("startTime")); + assertNotNull(cursor.toList().get(1).get("startTime")); + } + + @Test + public void testIssue93() { + NitriteCollection coll = db.getCollection("orderByOnNullableColumn2"); + + coll.remove(ALL); + + Document doc = createDocument().put("id", "test-2").put("group", "groupA"); + assertEquals(1, coll.insert(doc).getAffectedCount()); + + doc = createDocument().put("id", "test-1").put("group", "groupA"); + assertEquals(1, coll.insert(doc).getAffectedCount()); + + DocumentCursor cursor = coll.find(where("group").eq("groupA"), + orderBy("startTime", SortOrder.Descending)); + assertEquals(2, cursor.size()); + } + + + @Test + public void testDefaultNullOrder() { + NitriteCollection coll = db.getCollection("test"); + try { + coll.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "startTime"); + } catch (IndexingException e) { + // ignore + } + + coll.remove(ALL); + + Document doc1 = createDocument().put("id", "test-1").put("group", "groupA"); + assertEquals(1, coll.insert(doc1).getAffectedCount()); + + Document doc2 = createDocument().put("id", "test-2").put("group", "groupA").put("startTime", DateTime.now()); + assertEquals(1, coll.insert(doc2).getAffectedCount()); + + Document doc3 = createDocument().put("id", "test-3").put("group", "groupA").put("startTime", DateTime.now().plusMinutes(1)); + assertEquals(1, coll.insert(doc3).getAffectedCount()); + + DocumentCursor cursor = coll.find(where("group").eq("groupA"), + orderBy("startTime", SortOrder.Descending)); + assertEquals(3, cursor.size()); + assertThat(Arrays.asList(doc3, doc2, doc1), + is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); + + + cursor = coll.find(where("group").eq("groupA"), + orderBy("startTime", SortOrder.Ascending)); + assertEquals(3, cursor.size()); + assertThat(Arrays.asList(doc1, doc2, doc3), + is(cursor.toList().stream().map(CollectionFindTest::trimMeta).collect(Collectors.toList()))); + } + + @Test + public void testFindFilterInvalidAccessor() { + insert(); + DocumentCursor cursor = collection.find(where("lastName.name").eq("ln2")); + assertEquals(cursor.size(), 0); + } + + @Test + public void testIssue144() { + Document doc1 = createDocument().put("id", "test-1").put("fruit", "Apple"); + Document doc2 = createDocument().put("id", "test-2").put("fruit", "Ôrange"); + Document doc3 = createDocument().put("id", "test-3").put("fruit", "Pineapple"); + + NitriteCollection coll = db.getCollection("test"); + coll.insert(doc1, doc2, doc3); + + DocumentCursor cursor = coll.find(orderBy("fruit", SortOrder.Ascending) + .collator(Collator.getInstance(Locale.FRANCE))); + assertEquals(cursor.toList().get(1).get("fruit"), "Ôrange"); + } + + @Test + public void testIdSet() { + insert(); + DocumentCursor cursor = collection.find(where("lastName").eq("ln2")); + assertEquals(cursor.size(), 2); + + cursor = collection.find(where("lastName").eq("ln1")); + assertEquals(cursor.size(), 1); + + Document byId = cursor.iterator().next(); + assertEquals(byId.get("lastName"), "ln1"); + } + + @Test + public void testCollectionField() { + Document document = createDocument("name", "John") + .put("tags", new Document[]{ + createDocument("type", "example").put("other", "value"), + createDocument("type", "another-example").put("other", "some-other-value") + }); + + NitriteCollection example = db.getCollection("example"); + example.insert(document); + + document = createDocument("name", "Jane") + .put("tags", new Document[]{ + createDocument("type", "example2").put("other", "value2"), + createDocument("type", "another-example2").put("other", "some-other-value2") + }); + example.insert(document); + + DocumentCursor cursor = example.find(where("tags").elemMatch(where("type").eq("example"))); + for (Document doc : cursor) { + assertNotNull(doc); + assertEquals(doc.get("name"), "John"); + } + } + + @Test + public void testBetweenFilter() { + Document doc1 = createDocument("age", 31).put("tag", "one"); + Document doc2 = createDocument("age", 32).put("tag", "two"); + Document doc3 = createDocument("age", 33).put("tag", "three"); + Document doc4 = createDocument("age", 34).put("tag", "four"); + Document doc5 = createDocument("age", 35).put("tag", "five"); + + NitriteCollection collection = db.getCollection("tag"); + collection.insert(doc1, doc2, doc3, doc4, doc5); + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "age"); + + DocumentCursor cursor = collection.find(where("age").between(31, 35)); + assertEquals(cursor.size(), 5); + + cursor = collection.find(where("age").between(31, 35, false)); + assertEquals(cursor.size(), 3); + + cursor = collection.find(where("age").between(31, 35, false, true)); + assertEquals(cursor.size(), 4); + + cursor = collection.find(where("age").between(31, 35, false).not()); + assertEquals(cursor.size(), 2); + } + + @Test + public void testByIdFilter() { + Document doc1 = createDocument("age", 31).put("tag", "one"); + Document doc2 = createDocument("age", 32).put("tag", "two"); + Document doc3 = createDocument("age", 33).put("tag", "three"); + Document doc4 = createDocument("age", 34).put("tag", "four"); + Document doc5 = createDocument("age", 35).put("tag", "five"); + + NitriteCollection collection = db.getCollection("tag"); + collection.insert(doc1, doc2, doc3, doc4, doc5); + + List documentList = collection.find().toList(); + Document document = documentList.get(0); + NitriteId nitriteId = document.getId(); + + Document result = collection.find(byId(nitriteId)).firstOrNull(); + assertEquals(document, result); + + result = collection.find(and(byId(nitriteId), where("age").notEq(null))).firstOrNull(); + assertEquals(document, result); + + result = collection.find(or(byId(nitriteId), where("tag").eq(document.get("tag")))).firstOrNull(); + assertEquals(document, result); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionIndexNegativeTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionIndexNegativeTest.java new file mode 100644 index 000000000..5e9fff277 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionIndexNegativeTest.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.exceptions.UniqueConstraintException; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.index.IndexOptions; +import org.junit.Test; + +import static org.dizitart.no2.index.IndexType.FULL_TEXT; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionIndexNegativeTest extends BaseCollectionTest { + + @Test(expected = UniqueConstraintException.class) + public void testCreateInvalidUniqueIndex() { + collection.createIndex("lastName"); + assertTrue(collection.hasIndex("lastName")); + insert(); + } + + @Test(expected = UniqueConstraintException.class) + public void testCreateIndexOnArray() { + collection.createIndex("data"); + assertTrue(collection.hasIndex("data")); + // data array field has repetition, so unique constraint exception + insert(); + } + + @Test(expected = UniqueConstraintException.class) + public void testCreateOnInvalidField() { + insert(); + collection.createIndex("my-value"); + assertTrue(collection.hasIndex("my-value")); + } + + @Test(expected = IndexingException.class) + public void testCreateFullTextOnNonTextField() { + insert(); + collection.createIndex(IndexOptions.indexOptions(FULL_TEXT), "birthDay"); + assertTrue(collection.hasIndex("birthDay")); + } + + @Test(expected = IndexingException.class) + public void testDropIndexOnNonIndexedField() { + collection.dropIndex("data"); + } + + @Test(expected = IndexingException.class) + public void testRebuildIndexInvalid() { + collection.rebuildIndex("unknown"); + } + + @Test(expected = IndexingException.class) + public void testMultipleTextIndex() { + collection.createIndex(IndexOptions.indexOptions(FULL_TEXT), "body", "lastName"); + } + + @Test(expected = ValidationException.class) + public void testIndexOnNullField() { + collection.createIndex(IndexOptions.indexOptions(FULL_TEXT)); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionIndexTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionIndexTest.java new file mode 100644 index 000000000..84fd453ac --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionIndexTest.java @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Random; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionIndexTest extends BaseCollectionTest { + + @Test + public void testCreateIndex() { + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + + collection.createIndex("birthDay"); + assertTrue(collection.hasIndex("birthDay")); + + insert(); + } + + @Test + public void testListIndexes() { + assertEquals(collection.listIndices().size(), 0); + + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + + assertEquals(collection.listIndices().size(), 3); + } + + @Test + public void testDropIndex() { + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.dropIndex("firstName"); + assertFalse(collection.hasIndex("firstName")); + } + + @Test + public void testDropAllIndexes() { + collection.dropAllIndices(); + + testCreateIndex(); + assertEquals(collection.listIndices().size(), 4); + + collection.dropAllIndices(); + assertEquals(collection.listIndices().size(), 0); + } + + @Test + public void testHasIndex() { + assertFalse(collection.hasIndex("lastName")); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + assertFalse(collection.hasIndex("body")); + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + } + + @Test + public void testDeleteWithIndex() { + collection.createIndex("firstName"); + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + + insert(); + + WriteResult result = collection.remove(where("firstName").eq("fn1")); + assertEquals(result.getAffectedCount(), 1); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 2); + + result = collection.remove(where("body").text("Lorem")); + assertEquals(result.getAffectedCount(), 1); + + cursor = collection.find(); + assertEquals(cursor.size(), 1); + } + + @Test + public void testRebuildIndex() { + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + insert(); + Collection indices = collection.listIndices(); + for (IndexDescriptor idx : indices) { + collection.rebuildIndex(idx.getIndexFields().getFieldNames().toArray(new String[0])); + } + } + + @Test + public void testNullValueInIndexedField() { + collection.createIndex("firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "birthDay"); + insert(); + + Document document = createDocument("firstName", null) + .put("lastName", "ln1") + .put("birthDay", null) + .put("data", new byte[]{1, 2, 3}) + .put("list", new ArrayList() {{ + add("one"); + add("two"); + add("three"); + }}) + .put("body", "a quick brown fox jump over the lazy dog"); + + collection.insert(document); + } + + @Test + public void testDropAllAndCreateIndex() { + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + collection.dropAllIndices(); + assertFalse(collection.hasIndex("firstName")); + + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection = db.getCollection("test"); + assertTrue(collection.hasIndex("firstName")); + } + + @Test + public void testIssue178() { + collection.dropAllIndices(); + collection.remove(Filter.ALL); + + Document doc1 = createDocument("field", 5); + Document doc2 = createDocument("field", 4.3); + Document doc3 = createDocument("field", 0.03); + Document doc4 = createDocument("field", 4); + Document doc5 = createDocument("field", 5.0); + + collection.insert(doc1, doc2, doc3, doc4, doc5); + + DocumentCursor cursor = collection.find(where("field").eq(5)); + assertEquals(cursor.size(), 1); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "field"); + + cursor = collection.find(where("field").eq(5)); + assertEquals(cursor.size(), 1); + } + + @Test + public void testIndexEvent() { + NitriteCollection collection = db.getCollection("index-test"); + Random random = new Random(); + for (int i = 0; i < 10000; i++) { + Document document = createDocument("first", random.nextInt()) + .put("second", random.nextDouble()); + collection.insert(document); + } + + collection.subscribe(eventInfo -> { + switch (eventInfo.getEventType()) { + case Insert: + fail("wrong event Insert"); + break; + case Update: + fail("wrong event Update"); + break; + case Remove: + fail("wrong event Remove"); + break; + case IndexStart: + case IndexEnd: + break; + } + assertTrue(eventInfo.getItem() instanceof String); + System.out.println(eventInfo.getEventType() + " for field " + eventInfo.getItem()); + }); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "first"); + assertEquals(collection.find().size(), 10000); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "second"); + assertEquals(collection.find().size(), 10000); + } + + @Test + public void testIndexAndSearchOnNullValues() { + NitriteCollection collection = db.getCollection("index-on-null"); + collection.insert(createDocument("first", null).put("second", 123).put("third", new Integer[]{1, 2, null})); + collection.insert(createDocument("first", "abcd").put("second", 456).put("third", new int[]{3, 1})); + collection.insert(createDocument("first", "xyz").put("second", 789).put("third", null)); + + collection.createIndex("first"); + assertEquals(collection.find(where("first").eq(null)).size(), 1); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "third"); + assertEquals(collection.find(where("third").eq(null)).size(), 2); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionInsertNegativeTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionInsertNegativeTest.java new file mode 100644 index 000000000..02358caf6 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionInsertNegativeTest.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.exceptions.UniqueConstraintException; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionInsertNegativeTest extends BaseCollectionTest { + @Test(expected = UniqueConstraintException.class) + public void testMultipleInsert() { + WriteResult result = collection.insert(doc1, doc2, doc3); + assertEquals(result.getAffectedCount(), 3); + Document document = collection.find().firstOrNull(); + collection.insert(document); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionInsertTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionInsertTest.java new file mode 100644 index 000000000..cd9558946 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionInsertTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.common.WriteResult; +import org.junit.Test; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.common.Constants.DOC_ID; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class CollectionInsertTest extends BaseCollectionTest { + + @Test + public void testInsert() { + WriteResult result = collection.insert(doc1, doc2, doc3); + assertEquals(result.getAffectedCount(), 3); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 3); + + for (Document document : cursor) { + assertNotNull(document.get("firstName")); + assertNotNull(document.get("lastName")); + assertNotNull(document.get("birthDay")); + assertNotNull(document.get("data")); + assertNotNull(document.get("body")); + assertNotNull(document.get(DOC_ID)); + } + } + + @Test + public void testInsertHeteroDocs() { + Document document = createDocument("test", "Nitrite Test"); + + WriteResult result = collection.insert(doc1, doc2, doc3, document); + assertEquals(result.getAffectedCount(), 4); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionJoinTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionJoinTest.java new file mode 100644 index 000000000..caff44d61 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionJoinTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import lombok.extern.slf4j.Slf4j; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.Lookup; +import org.dizitart.no2.common.RecordStream; +import org.junit.Before; +import org.junit.Test; + +import java.util.Collection; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.Filter.ALL; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +@Slf4j +public class CollectionJoinTest extends BaseCollectionTest { + private NitriteCollection foreignCollection; + + @Before + @Override + public void setUp() { + try { + super.setUp(); + foreignCollection = db.getCollection("foreign"); + foreignCollection.remove(ALL); + + Document fdoc1 = createDocument("fName", "fn1") + .put("address", "ABCD Street") + .put("telephone", "123456789"); + + Document fdoc2 = createDocument("fName", "fn2") + .put("address", "XYZ Street") + .put("telephone", "000000000"); + + Document fdoc3 = createDocument("fName", "fn2") + .put("address", "Some other Street") + .put("telephone", "7893141321"); + + foreignCollection.insert(fdoc1, fdoc2, fdoc3); + } catch (Throwable t) { + log.error("Error while initializing test database", t); + } + } + + @Test + @SuppressWarnings("unchecked") + public void testJoinAll() { + insert(); + + Lookup lookup = new Lookup(); + lookup.setLocalField("firstName"); + lookup.setForeignField("fName"); + lookup.setTargetField("personalDetails"); + + RecordStream result = collection.find().join(foreignCollection.find(), lookup); + assertEquals(result.size(), 3); + + for (Document document : result) { + if (document.get("firstName") == "fn1") { + Collection personalDetails = (Collection) document.get("personalDetails"); + assertNotNull(personalDetails); + assertEquals(personalDetails.size(), 1); + Object[] details = personalDetails.toArray(); + assertEquals(((Document) details[0]).get("telephone"), "123456789"); + } else if (document.get("firstName") == "fn2") { + Collection personalDetails = (Collection) document.get("personalDetails"); + assertNotNull(personalDetails); + assertEquals(personalDetails.size(), 2); + Object[] details = personalDetails.toArray(); + for (Object o : details) { + Document d = (Document) o; + if (d.get("address").equals("XYZ Street")) { + assertEquals(d.get("telephone"), "000000000"); + } else { + assertEquals(d.get("telephone"), "7893141321"); + } + } + } else if (document.get("firstName") == "fn3") { + assertNull(document.get("personalDetails")); + } + System.out.println(document); + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionSingleFieldIndexNegativeTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionSingleFieldIndexNegativeTest.java new file mode 100644 index 000000000..b459e469b --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionSingleFieldIndexNegativeTest.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.exceptions.UniqueConstraintException; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionSingleFieldIndexNegativeTest extends BaseCollectionTest { + + @Test(expected = UniqueConstraintException.class) + public void testCreateInvalidUniqueIndex() { + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + insert(); + } + + @Test(expected = UniqueConstraintException.class) + public void testCreateIndexOnArray() { + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "data"); + assertTrue(collection.hasIndex("data")); + // data array field has repetition, so unique constraint exception + insert(); + } + + @Test(expected = UniqueConstraintException.class) + public void testCreateOnInvalidField() { + insert(); + // multiple null value will be created + collection.createIndex(IndexOptions.indexOptions(IndexType.UNIQUE), "my-value"); + assertTrue(collection.hasIndex("my-value")); + } + + @Test(expected = IndexingException.class) + public void testCreateFullTextOnNonTextField() { + insert(); + collection.createIndex(IndexOptions.indexOptions(IndexType.FULL_TEXT), "birthDay"); + assertTrue(collection.hasIndex("birthDay")); + } + + @Test(expected = IndexingException.class) + public void testDropIndexOnNonIndexedField() { + collection.dropIndex("data"); + } + + @Test(expected = IndexingException.class) + public void testRebuildIndexInvalid() { + collection.rebuildIndex("unknown"); + } + + @Test(expected = IndexingException.class) + public void createMultipleIndexTypeOnSameField() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "lastName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionSingleFieldIndexTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionSingleFieldIndexTest.java new file mode 100644 index 000000000..fe37845e1 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionSingleFieldIndexTest.java @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.IndexType; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Random; +import java.util.concurrent.Callable; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.awaitility.Awaitility.await; +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class CollectionSingleFieldIndexTest extends BaseCollectionTest { + + @Test + public void testCreateIndex() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + + collection.createIndex("birthDay"); + assertTrue(collection.hasIndex("birthDay")); + + insert(); + } + + @Test + public void testListIndexes() { + assertEquals(collection.listIndices().size(), 0); + + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + + assertEquals(collection.listIndices().size(), 3); + } + + @Test + public void testDropIndex() { + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection.dropIndex("firstName"); + assertFalse(collection.hasIndex("firstName")); + } + + @Test + public void testDropAllIndexes() { + collection.dropAllIndices(); + + testCreateIndex(); + assertEquals(collection.listIndices().size(), 4); + + collection.dropAllIndices(); + assertEquals(collection.listIndices().size(), 0); + } + + @Test + public void testHasIndex() { + assertFalse(collection.hasIndex("lastName")); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + assertTrue(collection.hasIndex("lastName")); + + assertFalse(collection.hasIndex("body")); + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + assertTrue(collection.hasIndex("body")); + } + + @Test + public void testDeleteWithIndex() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName"); + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + + insert(); + + WriteResult result = collection.remove(where("firstName").eq("fn1")); + assertEquals(result.getAffectedCount(), 1); + + DocumentCursor cursor = collection.find(); + assertEquals(cursor.size(), 2); + + result = collection.remove(where("body").text("Lorem")); + assertEquals(result.getAffectedCount(), 1); + + cursor = collection.find(); + assertEquals(cursor.size(), 1); + } + + @Test + public void testRebuildIndex() { + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + insert(); + Collection indices = collection.listIndices(); + for (IndexDescriptor idx : indices) { + collection.rebuildIndex(idx.getIndexFields().getFieldNames().toArray(new String[0])); + } + } + + @Test + public void testRebuildIndexOnRunningIndex() { + collection.createIndex(indexOptions(IndexType.FULL_TEXT), "body"); + insert(); + collection.rebuildIndex("body"); + + boolean error = false; + try { + collection.rebuildIndex("body"); + } catch (IndexingException ie) { + error = true; + } finally { + assertFalse(error); + await().until(bodyIndexingCompleted()); + } + } + + private Callable bodyIndexingCompleted() { + return () -> !collection.isIndexing("body"); + } + + @Test + public void testNullValueInIndexedField() { + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "birthDay"); + insert(); + + Document document = createDocument("firstName", null) + .put("lastName", "ln1") + .put("birthDay", null) + .put("data", new byte[]{1, 2, 3}) + .put("list", new ArrayList() {{ + add("one"); + add("two"); + add("three"); + }}) + .put("body", "a quick brown fox jump over the lazy dog"); + + collection.insert(document); + } + + @Test + public void testDropAllAndCreateIndex() { + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + collection.dropAllIndices(); + assertFalse(collection.hasIndex("firstName")); + + collection.createIndex("firstName"); + assertTrue(collection.hasIndex("firstName")); + + collection = db.getCollection("test"); + assertTrue(collection.hasIndex("firstName")); + } + + @Test + public void testIssue178() { + collection.dropAllIndices(); + collection.remove(Filter.ALL); + + Document doc1 = createDocument("field", 5); + Document doc2 = createDocument("field", 4.3); + Document doc3 = createDocument("field", 0.03); + Document doc4 = createDocument("field", 4); + Document doc5 = createDocument("field", 5.0); + + collection.insert(doc1, doc2, doc3, doc4, doc5); + + DocumentCursor cursor = collection.find(where("field").eq(5)); + assertEquals(cursor.size(), 1); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "field"); + + cursor = collection.find(where("field").eq(5)); + assertEquals(cursor.size(), 1); + } + + @Test + public void testIndexEvent() { + NitriteCollection collection = db.getCollection("index-test"); + Random random = new Random(); + for (int i = 0; i < 10000; i++) { + Document document = createDocument("first", random.nextInt()) + .put("second", random.nextDouble()); + collection.insert(document); + } + + AtomicBoolean failed = new AtomicBoolean(false); + AtomicBoolean completed = new AtomicBoolean(false); + collection.subscribe(eventInfo -> { + switch (eventInfo.getEventType()) { + case Insert: + case Remove: + case Update: + failed.set(true); + break; + case IndexStart: + case IndexEnd: + completed.set(true); + break; + } + }); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "first"); + assertEquals(collection.find().size(), 10000); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "second"); + assertEquals(collection.find().size(), 10000); + + await().until(completed::get); + assertFalse(failed.get()); + } + + @Test + public void testIndexAndSearchOnNullValues() { + NitriteCollection collection = db.getCollection("index-on-null"); + collection.insert(createDocument("first", null).put("second", 123).put("third", new Integer[]{1, 2, null})); + collection.insert(createDocument("first", "abcd").put("second", 456).put("third", new int[]{3, 1})); + collection.insert(createDocument("first", "xyz").put("second", 789).put("third", null)); + + collection.createIndex(indexOptions(IndexType.UNIQUE), "first"); + assertEquals(collection.find(where("first").eq(null)).size(), 1); + + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "third"); + assertEquals(collection.find(where("third").eq(null)).size(), 2); + } + + @Test + public void testCreateCompoundAndSingleFieldIndexOnSameField() { + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + collection.createIndex(indexOptions(IndexType.UNIQUE), "firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName", "firstName"); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionUpdateTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionUpdateTest.java new file mode 100644 index 000000000..86bff59b5 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/collection/CollectionUpdateTest.java @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.UpdateOptions; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.exceptions.NitriteIOException; +import org.dizitart.no2.exceptions.NotIdentifiableException; +import org.dizitart.no2.exceptions.UniqueConstraintException; +import org.dizitart.no2.filters.Filter; +import org.junit.Test; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.common.util.DocumentUtils.isSimilar; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + +public class CollectionUpdateTest extends BaseCollectionTest { + + @Test + public void testUpdate() { + insert(); + + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + for (Document document : cursor) { + assertEquals(document.get("lastName"), "ln1"); + } + + WriteResult updateResult = collection.update(where("firstName").eq("fn1"), + createDocument("lastName", "new-last-name")); + assertEquals(updateResult.getAffectedCount(), 1); + + cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + for (Document document : cursor) { + assertEquals(document.get("lastName"), "new-last-name"); + } + } + + @Test(expected = NotIdentifiableException.class) + public void testUpsertWithoutId() { + insert(); + Document update = createDocument("lastName", "ln4"); + WriteResult writeResult = collection.update(update, false); + assertEquals(writeResult.getAffectedCount(), 0); + assertEquals(collection.size(), 3); + } + + @Test + public void testUpsert() { + insert(); + assertEquals(collection.size(), 3); + + Document update = createDocument("lastName", "ln4"); + WriteResult writeResult = collection.update(update, true); + assertEquals(writeResult.getAffectedCount(), 1); + assertEquals(collection.size(), 4); + + Document document = collection.find(where("lastName").eq("ln4")) + .firstOrNull(); + assertTrue(isSimilar(document, update, "lastName")); + } + + @Test + public void testOptionUpsert() { + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 0); + + WriteResult updateResult = collection.update(where("firstName").eq("fn1"), + doc1, UpdateOptions.updateOptions(true)); + assertEquals(updateResult.getAffectedCount(), 1); + + cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + for (Document document : cursor) { + assertTrue(isSimilar(document, doc1, "firstName", "lastName", "birthDay", "data", "list", "body")); + } + } + + @Test + public void testUpdateMultiple() { + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 0); + + insert(); + + Document document = createDocument("lastName", "newLastName1"); + WriteResult updateResult = collection.update(where("firstName").eq("fn1").not(), + document); + assertEquals(updateResult.getAffectedCount(), 2); + + cursor = collection.find(where("lastName").eq("newLastName1")); + assertEquals(cursor.size(), 2); + } + + @Test + public void testUpdateWithOptionsUpsertFalse() { + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 0); + + UpdateOptions updateOptions = new UpdateOptions(); + updateOptions.setInsertIfAbsent(false); + + WriteResult updateResult = collection.update(where("firstName").eq("fn1"), + doc1, updateOptions); + assertEquals(updateResult.getAffectedCount(), 0); + + cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 0); + } + + @Test + public void testUpdateMultipleWithJustOnceFalse() { + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 0); + + insert(); + + UpdateOptions updateOptions = new UpdateOptions(); + updateOptions.setJustOnce(false); + + Document document = createDocument("lastName", "newLastName1"); + WriteResult updateResult = collection.update(where("firstName").eq("fn1").not(), + document, updateOptions); + assertEquals(updateResult.getAffectedCount(), 2); + + cursor = collection.find(where("lastName").eq("newLastName1")); + assertEquals(cursor.size(), 2); + } + + @Test + public void testUpdateMultipleWithJustOnceTrue() { + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 0); + + insert(); + + UpdateOptions updateOptions = new UpdateOptions(); + updateOptions.setJustOnce(true); + + Document document = createDocument("lastName", "newLastName1"); + collection.update(where("firstName").eq("fn1").not(), + document, updateOptions); + } + + @Test + public void testUpdateWithNewField() { + insert(); + + DocumentCursor cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + for (Document document : cursor) { + assertEquals(document.get("lastName"), "ln1"); + } + + WriteResult updateResult = collection.update(where("firstName").eq("fn1"), + createDocument("new-value", "new-value-value")); + assertEquals(updateResult.getAffectedCount(), 1); + + cursor = collection.find(where("firstName").eq("fn1")); + assertEquals(cursor.size(), 1); + for (Document document : cursor) { + assertEquals(document.get("new-value"), "new-value-value"); + } + } + + @Test + public void testUpdateInvalidFilter() { + insert(); + + DocumentCursor cursor = collection.find(where("lastName").eq("ln1")); + assertEquals(cursor.size(), 1); + for (Document document : cursor) { + assertEquals(document.get("firstName"), "fn1"); + } + + // to check if NitriteId is valid. + WriteResult updateResult = collection.update(where("some-value").eq("some-value"), + createDocument("lastName", "new-last-name")); + assertEquals(updateResult.getAffectedCount(), 0); + } + + @Test + public void updateAfterAttributeRemoval() { + NitriteCollection coll = db.getCollection("test_updateAfterAttributeRemoval"); + coll.remove(Filter.ALL); + + Document doc = createDocument().put("id", "test-1").put("group", "groupA"); + assertEquals(1, coll.insert(doc).getAffectedCount()); + + Document savedDoc1 = coll.find().firstOrNull(); + assertNotNull(savedDoc1); + + Document clonedDoc1 = savedDoc1.clone(); + assertEquals(savedDoc1, clonedDoc1); + + clonedDoc1.put("group", null); +// clonedDoc1.remove("group"); + assertEquals(1, coll.update(clonedDoc1).getAffectedCount()); + + Document savedDoc2 = coll.find(Filter.ALL).firstOrNull(); + assertNotNull(savedDoc2); + assertNull(savedDoc2.get("group")); + } + + @Test(expected = NotIdentifiableException.class) + public void testUpdateWithoutId() { + NitriteCollection collection = db.getCollection("test"); + Document document = createDocument("test", "test123"); + collection.update(document); + } + + @Test(expected = NotIdentifiableException.class) + public void testRemoveWithoutId() { + NitriteCollection collection = db.getCollection("test"); + Document document = createDocument("test", "test123"); + collection.remove(document); + } + + @Test(expected = NitriteIOException.class) + public void testRegisterListenerAfterDrop() { + NitriteCollection collection = db.getCollection("test"); + collection.drop(); + collection.subscribe(changeInfo -> fail("should not happen")); + } + + @Test(expected = NitriteIOException.class) + public void testRegisterListenerAfterClose() throws Exception { + NitriteCollection collection = db.getCollection("test"); + collection.close(); + collection.subscribe(changeInfo -> fail("should not happen")); + } + + @Test(expected = UniqueConstraintException.class) + public void testIssue151() { + Document doc1 = createDocument().put("id", "test-1").put("fruit", "Apple"); + Document doc2 = createDocument().put("id", "test-2").put("fruit", "Ôrange"); + NitriteCollection coll = db.getCollection("test"); + coll.insert(doc1, doc2); + + coll.createIndex("fruit"); + + assertEquals(coll.find(where("fruit").eq("Apple")).size(), 1); + + Document doc3 = coll.find(where("id").eq("test-2")).firstOrNull(); + + doc3.put("fruit", "Apple"); + coll.update(doc3); + + assertEquals(coll.find(where("fruit").eq("Apple")).size(), 1); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/collection/FieldProcessorTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/collection/FieldProcessorTest.java new file mode 100644 index 000000000..0055f97ac --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/collection/FieldProcessorTest.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.collection; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.common.crypto.AESEncryptor; +import org.dizitart.no2.common.crypto.Encryptor; +import org.dizitart.no2.common.processors.Processor; +import org.dizitart.no2.common.processors.StringFieldEncryptionProcessor; +import org.dizitart.no2.exceptions.NitriteSecurityException; +import org.dizitart.no2.store.NitriteMap; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.nio.charset.StandardCharsets; +import java.util.Date; +import java.util.List; + +import static org.dizitart.no2.common.util.Iterables.toList; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class FieldProcessorTest extends BaseCollectionTest { + + private Encryptor encryptor; + private NitriteCollection collection; + private Processor cvvProcessor; + + @Before + public void setUp() { + super.setUp(); + + encryptor = new AESEncryptor("s3k4e8"); + cvvProcessor = new Processor() { + @Override + public Document processBeforeWrite(Document document) { + String cvv = document.get("cvv", String.class); + String encryptedCvv = encryptor.encrypt(cvv.getBytes(StandardCharsets.UTF_8)); + document.put("cvv", encryptedCvv); + return document; + } + + @Override + public Document processAfterRead(Document document) { + String encryptedCvv = document.get("cvv", String.class); + String cvv = encryptor.decrypt(encryptedCvv); + document.put("cvv", cvv); + return document; + } + }; + StringFieldEncryptionProcessor creditCardProcessor = new StringFieldEncryptionProcessor(encryptor); + creditCardProcessor.addFields("creditCardNumber"); + + collection = db.getCollection("encryption-test"); + collection.addProcessor(creditCardProcessor); + + Document document = Document.createDocument("name", "John Doe") + .put("creditCardNumber", "5548960345687452") + .put("cvv", "007") + .put("expiryDate", new Date()); + collection.insert(document); + + document = Document.createDocument("name", "Jane Doe") + .put("creditCardNumber", "5500960345687452") + .put("cvv", "008") + .put("expiryDate", new Date()); + collection.insert(document); + + collection.addProcessor(cvvProcessor); + } + + @Test + public void testFieldEncryptionInNitriteMap() { + NitriteMap nitriteMap = collection.getStore().openMap("encryption-test", + NitriteId.class, Document.class); + + List documents = toList(nitriteMap.values()); + for (Document document : documents) { + if (document.get("creditCardNumber", String.class).equalsIgnoreCase("5548960345687452")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("creditCardNumber", String.class).equalsIgnoreCase("5500960345687452")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("cvv", String.class).equalsIgnoreCase("008")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("cvv", String.class).equalsIgnoreCase("007")) { + Assert.fail("unencrypted secret text found"); + } + } + } + + @Test + public void testSuccessfulDecryption() { + Document document = collection.find(where("name").eq("Jane Doe")).firstOrNull(); + assertNotNull(document); + + assertEquals(document.get("creditCardNumber", String.class), "5500960345687452"); + assertEquals(document.get("cvv", String.class), "008"); + + document = collection.find(where("name").eq("John Doe")).firstOrNull(); + assertNotNull(document); + + assertEquals(document.get("creditCardNumber", String.class), "5548960345687452"); + assertEquals(document.get("cvv", String.class), "007"); + } + + @Test(expected = NitriteSecurityException.class) + public void testFailedDecryption() { + Encryptor wrongEncryptor = new AESEncryptor("secret"); + + collection = db.getCollection("encryption-test"); + collection.addProcessor(new Processor() { + @Override + public Document processBeforeWrite(Document document) { + String creditCardNumber = document.get("creditCardNumber", String.class); + String encryptedCreditCardNumber = encryptor.encrypt(creditCardNumber.getBytes(StandardCharsets.UTF_8)); + document.put("creditCardNumber", encryptedCreditCardNumber); + return document; + } + + @Override + public Document processAfterRead(Document document) { + String encryptedCreditCardNumber = document.get("creditCardNumber", String.class); + String creditCardNumber = wrongEncryptor.decrypt(encryptedCreditCardNumber); + document.put("creditCardNumber", creditCardNumber); + return document; + } + }); + + Document document = Document.createDocument("name", "John Doe") + .put("creditCardNumber", "5548960345687452") + .put("cvv", "007") + .put("expiryDate", new Date()); + collection.insert(document); + + document = Document.createDocument("name", "Jane Doe") + .put("creditCardNumber", "5500960345687452") + .put("cvv", "008") + .put("expiryDate", new Date()); + collection.insert(document); + + collection.find(where("name").eq("Jane Doe")).firstOrNull(); + } + + @Test + public void testSearchOnEncryptedField() { + Document document = collection.find(where("cvv").eq("008")).firstOrNull(); + assertNull(document); + } + + @Test + public void testUpdateEncryptedField() { + Document document = Document.createDocument("name", "John Doe") + .put("creditCardNumber", "00000000000000") + .put("cvv", "007") + .put("expiryDate", new Date()); + + WriteResult writeResult = collection.update(where("name").eq("John Doe"), document); + assertEquals(writeResult.getAffectedCount(), 1); + + document = collection.find(where("name").eq("John Doe")).firstOrNull(); + assertNotNull(document); + + assertEquals(document.get("creditCardNumber", String.class), "00000000000000"); + assertEquals(document.get("cvv", String.class), "007"); + } + + @Test + public void testIndexOnEncryptedField() { + collection.createIndex("cvv"); + Document document = collection.find(where("cvv").eq("008")).firstOrNull(); + assertNull(document); + } + + @Test + public void testRemoveProcessor() { + Document document = collection.find(where("cvv").eq("008")).firstOrNull(); + assertNull(document); + + collection.removeProcessor(cvvProcessor); + + document = collection.find(where("cvv").eq("008")).firstOrNull(); + assertNotNull(document); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/BaseObjectRepositoryTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/BaseObjectRepositoryTest.java new file mode 100644 index 000000000..f3ae1b720 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/BaseObjectRepositoryTest.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteBuilder; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.integration.repository.data.*; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.Arrays; +import java.util.Collection; + +import static org.dizitart.no2.filters.Filter.ALL; + +@RunWith(value = Parameterized.class) +public abstract class BaseObjectRepositoryTest { + @Parameterized.Parameter + public boolean isProtected = false; + + protected Nitrite db; + protected ObjectRepository companyRepository; + protected ObjectRepository employeeRepository; + protected ObjectRepository aObjectRepository; + protected ObjectRepository cObjectRepository; + protected ObjectRepository bookRepository; + + @Rule + public Retry retry = new Retry(3); + + @Parameterized.Parameters(name = "Protected = {0}") + public static Collection data() { + return Arrays.asList(new Object[][]{ + {false}, + {true}, + }); + } + + @Before + public void setUp() { + openDb(); + + companyRepository = db.getRepository(Company.class); + employeeRepository = db.getRepository(Employee.class); + + aObjectRepository = db.getRepository(ClassA.class); + cObjectRepository = db.getRepository(ClassC.class); + + bookRepository = db.getRepository(Book.class); + + for (int i = 0; i < 10; i++) { + Company company = DataGenerator.generateCompanyRecord(); + companyRepository.insert(company); + Employee employee = DataGenerator.generateEmployee(); + employee.setEmpId((long) i + 1); + employeeRepository.insert(employee); + + aObjectRepository.insert(ClassA.create(i + 50)); + cObjectRepository.insert(ClassC.create(i + 30)); + + Book book = DataGenerator.randomBook(); + bookRepository.insert(book); + } + } + + private void openDb() { + NitriteBuilder nitriteBuilder = Nitrite.builder() + .fieldSeparator("."); + + if (isProtected) { + db = nitriteBuilder.openOrCreate("test-user", "test-password"); + } else { + db = nitriteBuilder.openOrCreate(); + } + } + + @After + public void clear() throws Exception { + if (companyRepository != null && !companyRepository.isDropped()) { + companyRepository.remove(ALL); + } + + if (employeeRepository != null && !employeeRepository.isDropped()) { + employeeRepository.remove(ALL); + } + + if (aObjectRepository != null && !aObjectRepository.isDropped()) { + aObjectRepository.remove(ALL); + } + + if (cObjectRepository != null && !cObjectRepository.isDropped()) { + cObjectRepository.remove(ALL); + } + + if (bookRepository != null && !bookRepository.isDropped()) { + bookRepository.remove(ALL); + } + + if (db != null && !db.isClosed()) { + db.commit(); + db.close(); + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/CustomFieldSeparatorTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/CustomFieldSeparatorTest.java new file mode 100644 index 000000000..fe768e51a --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/CustomFieldSeparatorTest.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; +import org.dizitart.no2.repository.annotations.Indices; +import org.dizitart.no2.integration.repository.data.Company; +import org.dizitart.no2.integration.repository.data.Note; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.Serializable; +import java.util.Date; + +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee + */ +public class CustomFieldSeparatorTest { + private Nitrite db; + private ObjectRepository repository; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + db = Nitrite.builder() + .fieldSeparator(":") + .openOrCreate(); + + repository = db.getRepository(EmployeeForCustomSeparator.class); + } + + @After + public void reset() { + (new NitriteConfig()).fieldSeparator("."); + if (db != null && !db.isClosed()) { + db.close(); + } + } + + @Test + public void testFieldSeparator() { + assertEquals(NitriteConfig.getFieldSeparator(), ":"); + } + + @Test + public void testFindByEmbeddedField() { + EmployeeForCustomSeparator employee = new EmployeeForCustomSeparator(); + employee.setCompany(new Company()); + employee.setEmployeeNote(new Note()); + + employee.setEmpId(123L); + employee.setJoinDate(new Date()); + employee.setBlob(new byte[0]); + employee.setAddress("Dummy address"); + + employee.getCompany().setCompanyId(987L); + employee.getCompany().setCompanyName("Dummy Company"); + employee.getCompany().setDateCreated(new Date()); + + employee.getEmployeeNote().setNoteId(567L); + employee.getEmployeeNote().setText("Dummy Note"); + + repository.insert(employee); + + assertEquals(repository.find(where("employeeNote.text").eq("Dummy Note")).size(), 0); + assertEquals(repository.find(where("employeeNote:text").text("Dummy Note")).size(), 1); + + assertEquals(repository.find(where("company.companyName").eq("Dummy Company")).size(), 0); + assertEquals(repository.find(where("company:companyName").eq("Dummy Company")).size(), 1); + } + + @ToString + @EqualsAndHashCode + @Indices({ + @Index(value = "joinDate", type = IndexType.NON_UNIQUE), + @Index(value = "address", type = IndexType.FULL_TEXT), + @Index(value = "employeeNote:text", type = IndexType.FULL_TEXT) + }) + public static class EmployeeForCustomSeparator implements Serializable, Mappable { + @Id + @Getter + @Setter + private Long empId; + + @Getter + @Setter + private Date joinDate; + + @Getter + @Setter + private String address; + + @Getter + @Setter + private Company company; + + @Getter + @Setter + private byte[] blob; + + @Getter + @Setter + private Note employeeNote; + + EmployeeForCustomSeparator() { + } + + public EmployeeForCustomSeparator(EmployeeForCustomSeparator copy) { + empId = copy.empId; + joinDate = copy.joinDate; + address = copy.address; + company = copy.company; + blob = copy.blob; + employeeNote = copy.employeeNote; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument().put("empId", empId) + .put("joinDate", joinDate) + .put("address", address) + .put("blob", blob) + .put("company", company.write(mapper)) + .put("employeeNote", employeeNote.write(mapper)); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + empId = document.get("empId", Long.class); + joinDate = document.get("joinDate", Date.class); + address = document.get("address", String.class); + blob = document.get("blob", byte[].class); + employeeNote = new Note(); + Document doc = document.get("employeeNote", Document.class); + employeeNote.read(mapper, doc); + company = new Company(); + doc = document.get("company", Document.class); + company.read(mapper, doc); + } + } + +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/FieldProcessorTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/FieldProcessorTest.java new file mode 100644 index 000000000..be50bff32 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/FieldProcessorTest.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.common.crypto.AESEncryptor; +import org.dizitart.no2.common.crypto.Encryptor; +import org.dizitart.no2.common.processors.Processor; +import org.dizitart.no2.common.processors.StringFieldEncryptionProcessor; +import org.dizitart.no2.exceptions.NitriteSecurityException; +import org.dizitart.no2.integration.repository.data.EncryptedPerson; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.store.NitriteMap; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.nio.charset.StandardCharsets; +import java.util.Date; +import java.util.List; + +import static org.dizitart.no2.common.util.Iterables.toList; +import static org.dizitart.no2.common.util.ObjectUtils.findRepositoryName; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class FieldProcessorTest extends BaseObjectRepositoryTest { + private ObjectRepository persons; + private StringFieldEncryptionProcessor fieldProcessor; + + @Before + public void setUp() { + super.setUp(); + persons = db.getRepository(EncryptedPerson.class); + fieldProcessor = new StringFieldEncryptionProcessor("s3k4e8"); + fieldProcessor.addFields("creditCardNumber", "cvv"); + + EncryptedPerson person = new EncryptedPerson(); + person.setName("John Doe"); + person.setCreditCardNumber("5548960345687452"); + person.setCvv("007"); + person.setExpiryDate(new Date()); + + persons.insert(person); + + persons.addProcessor(fieldProcessor); + + person = new EncryptedPerson(); + person.setName("Jane Doe"); + person.setCreditCardNumber("5500960345687452"); + person.setCvv("008"); + person.setExpiryDate(new Date()); + persons.insert(person); + } + + @Test + public void testFieldEncryptionInNitriteMap() { + NitriteMap nitriteMap = persons.getDocumentCollection().getStore() + .openMap(findRepositoryName(EncryptedPerson.class, null), NitriteId.class, Document.class); + + List documents = toList(nitriteMap.values()); + for (Document document : documents) { + if (document.get("creditCardNumber", String.class).equalsIgnoreCase("5548960345687452")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("creditCardNumber", String.class).equalsIgnoreCase("5500960345687452")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("cvv", String.class).equalsIgnoreCase("008")) { + Assert.fail("unencrypted secret text found"); + } + + if (document.get("cvv", String.class).equalsIgnoreCase("007")) { + Assert.fail("unencrypted secret text found"); + } + } + } + + @Test + public void testSuccessfulDecryption() { + EncryptedPerson person = persons.find(where("name").eq("Jane Doe")).firstOrNull(); + assertNotNull(person); + + assertEquals(person.getCreditCardNumber(), "5500960345687452"); + assertEquals(person.getCvv(), "008"); + + person = persons.find(where("name").eq("John Doe")).firstOrNull(); + assertNotNull(person); + + assertEquals(person.getCreditCardNumber(), "5548960345687452"); + assertEquals(person.getCvv(), "007"); + } + + @Test(expected = NitriteSecurityException.class) + public void testFailedDecryption() { + ObjectRepository testPersons = db.getRepository(EncryptedPerson.class, "test"); + + Encryptor encryptor = new AESEncryptor("secret"); + Encryptor wrongEncryptor = new AESEncryptor("secret", "AES/GCM/NoPadding", + 5, 5, 5); + + testPersons.addProcessor(new Processor() { + @Override + public Document processBeforeWrite(Document document) { + String creditCardNumber = document.get("creditCardNumber", String.class); + String encryptedCreditCardNumber = encryptor.encrypt(creditCardNumber.getBytes(StandardCharsets.UTF_8)); + document.put("creditCardNumber", encryptedCreditCardNumber); + return document; + } + + @Override + public Document processAfterRead(Document document) { + String encryptedCreditCardNumber = document.get("creditCardNumber", String.class); + String creditCardNumber = wrongEncryptor.decrypt(encryptedCreditCardNumber); + document.put("creditCardNumber", creditCardNumber); + return document; + } + }); + + EncryptedPerson person = new EncryptedPerson(); + person.setName("John Doe"); + person.setCreditCardNumber("5548960345687452"); + person.setCvv("007"); + person.setExpiryDate(new Date()); + + testPersons.insert(person); + + person = new EncryptedPerson(); + person.setName("Jane Doe"); + person.setCreditCardNumber("5500960345687452"); + person.setCvv("008"); + person.setExpiryDate(new Date()); + testPersons.insert(person); + + testPersons.find(where("name").eq("Jane Doe")).firstOrNull(); + } + + @Test + public void testSearchOnEncryptedField() { + EncryptedPerson person = persons.find(where("cvv").eq("008")).firstOrNull(); + assertNull(person); + } + + @Test + public void testUpdateEncryptedField() { + EncryptedPerson person = new EncryptedPerson(); + person.setName("John Doe"); + person.setCreditCardNumber("00000000000000"); + person.setCvv("007"); + person.setExpiryDate(new Date()); + + WriteResult writeResult = persons.update(where("name").eq("John Doe"), person); + assertEquals(writeResult.getAffectedCount(), 1); + + person = persons.find(where("name").eq("John Doe")).firstOrNull(); + assertNotNull(person); + + assertEquals(person.getCreditCardNumber(), "00000000000000"); + assertEquals(person.getCvv(), "007"); + } + + @Test + public void testIndexOnEncryptedField() { + persons.createIndex("cvv"); + EncryptedPerson person = persons.find(where("cvv").eq("008")).firstOrNull(); + assertNull(person); + } + + @Test + public void testRemoveProcessor() { + EncryptedPerson person = persons.find(where("cvv").eq("008")).firstOrNull(); + assertNull(person); + + person = persons.find(where("creditCardNumber").eq("5548960345687452")).firstOrNull(); + assertNull(person); + + persons.removeProcessor(fieldProcessor); + + person = persons.find(where("cvv").eq("008")).firstOrNull(); + assertNotNull(person); + + person = persons.find(where("creditCardNumber").eq("5548960345687452")).firstOrNull(); + assertNotNull(person); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/InternalClass.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/InternalClass.java new file mode 100644 index 000000000..1a52708ce --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/InternalClass.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Data +class InternalClass implements Mappable { + @Id + private long id; + private String name; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("id", id) + .put("name", name); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Long.class); + name = document.get("name", String.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/NitriteIdAsIdTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/NitriteIdAsIdTest.java new file mode 100644 index 000000000..cc1036d16 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/NitriteIdAsIdTest.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.integration.TestUtil; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.common.util.Iterables; +import org.dizitart.no2.exceptions.InvalidIdException; +import org.dizitart.no2.integration.repository.data.WithNitriteId; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * @author Anindya Chatterjee + */ +public class NitriteIdAsIdTest { + private Nitrite db; + private ObjectRepository repo; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void before() { + db = TestUtil.createDb(); + repo = db.getRepository(WithNitriteId.class); + } + + @After + public void after() throws Exception { + db.close(); + } + + @Test + public void testNitriteIdField() { + WithNitriteId item1 = new WithNitriteId(); + item1.name = "first"; + + WithNitriteId item2 = new WithNitriteId(); + item2.name = "second"; + + repo.insert(item1, item2); + + Cursor cursor = repo.find(); + for (WithNitriteId withNitriteId : cursor) { + System.out.println(withNitriteId.name); + assertNotNull(withNitriteId.idField); + } + + WithNitriteId withNitriteId = cursor.firstOrNull(); + withNitriteId.name = "third"; + + NitriteId id = withNitriteId.idField; + repo.update(withNitriteId); + + WithNitriteId byId = repo.getById(id); + assertEquals(withNitriteId, byId); + assertEquals(repo.size(), 2); + } + + @Test(expected = InvalidIdException.class) + public void setIdDuringInsert() { + WithNitriteId item1 = new WithNitriteId(); + item1.name = "first"; + item1.idField = NitriteId.newId(); + + repo.insert(item1); + } + + @Test + public void changeIdDuringUpdate() { + WithNitriteId item2 = new WithNitriteId(); + item2.name = "second"; + WriteResult result = repo.insert(item2); + NitriteId nitriteId = Iterables.firstOrNull(result); + WithNitriteId byId = repo.getById(nitriteId); + byId.idField = NitriteId.newId(); + + result = repo.update(byId); + assertEquals(result.getAffectedCount(), 0); + assertEquals(repo.size(), 1); + } + +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/ObjectCursorTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/ObjectCursorTest.java new file mode 100644 index 000000000..c5127bb0e --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/ObjectCursorTest.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.integration.repository.data.Employee; +import org.junit.Test; + +import java.util.AbstractCollection; + +/** + * @author Anindya Chatterjee + */ +public class ObjectCursorTest extends BaseObjectRepositoryTest { + + @Test(expected = ValidationException.class) + public void testProjectForInterface() { + Cursor cursor = employeeRepository.find(); + cursor.project(Comparable.class); + } + + @Test(expected = ValidationException.class) + public void testProjectForPrimitive() { + Cursor cursor = employeeRepository.find(); + cursor.project(int.class); + } + + @Test(expected = ValidationException.class) + public void testProjectForArray() { + Cursor cursor = employeeRepository.find(); + cursor.project(String[].class); + } + + @Test(expected = ValidationException.class) + public void testProjectForAbstractClass() { + Cursor cursor = employeeRepository.find(); + cursor.project(AbstractCollection.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryNegativeTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryNegativeTest.java new file mode 100644 index 000000000..91ced7232 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryNegativeTest.java @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.integration.TestUtil; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.exceptions.*; +import org.dizitart.no2.integration.repository.data.*; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class ObjectRepositoryNegativeTest { + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + db = TestUtil.createDb(); + } + + @After + public void close() throws Exception { + db.close(); + db = null; + } + + @Test(expected = ObjectMappingException.class) + public void testWithCircularReference() { + ObjectRepository repository = db.getRepository(WithCircularReference.class); + + WithCircularReference parent = new WithCircularReference(); + parent.setName("parent"); + WithCircularReference object = new WithCircularReference(); + object.setName("test"); + object.setParent(parent); + // circular reference + parent.setParent(object); + + WriteResult result = repository.insert(object); + for (NitriteId id : result) { + WithCircularReference instance = repository.getById(id); + assertEquals(instance.getName(), object.getName()); + assertEquals(instance.getParent().getName(), object.getParent().getName()); + } + } + + @Test(expected = ObjectMappingException.class) + public void testWithCustomConstructor() { + ObjectRepository repository = db.getRepository(WithCustomConstructor.class); + + WithCustomConstructor object = new WithCustomConstructor("test", 2L); + + WriteResult result = repository.insert(object); + for (NitriteId id : result) { + WithCustomConstructor instance = repository.getById(id); + assertEquals(object.getName(), instance.getName()); + assertEquals(object.getNumber(), instance.getNumber()); + } + } + + @Test(expected = InvalidIdException.class) + public void testWithEmptyStringId() { + ObjectRepository repository = db.getRepository(WithEmptyStringId.class); + WithEmptyStringId object = new WithEmptyStringId(); + object.setName(""); // empty id value + + WriteResult result = repository.insert(object); + for (NitriteId id : result) { + WithEmptyStringId instance = repository.getById(id); + assertEquals(instance, object); + } + } + + @Test(expected = InvalidIdException.class) + public void testWithNullId() { + ObjectRepository repository = db.getRepository(WithNullId.class); + WithNullId object = new WithNullId(); + + WriteResult result = repository.insert(object); + for (NitriteId id : result) { + WithNullId instance = repository.getById(id); + assertEquals(instance, object); + } + } + + @Test(expected = ValidationException.class) + public void testWithValueTypeRepository() { + ObjectRepository repository = db.getRepository(String.class); + repository.insert("test"); + } + + @Test(expected = InvalidOperationException.class) + public void testFindResultRemove() { + ObjectRepository repository = db.getRepository(Employee.class); + repository.insert(DataGenerator.generateEmployee()); + RecordStream result = repository.find(); + result.iterator().remove(); + } + + @Test(expected = IndexingException.class) + public void testWithObjectId() { + ObjectRepository repository = db.getRepository(WithObjectId.class); + WithOutId id = new WithOutId(); + id.setName("test"); + id.setNumber(1); + + WithObjectId object = new WithObjectId(); + object.setWithOutId(id); + repository.insert(object); + } + + @Test(expected = NotIdentifiableException.class) + public void testUpdateNoId() { + ObjectRepository repository = db.getRepository(WithOutId.class); + WithOutId object = new WithOutId(); + object.setName("name"); + object.setNumber(1L); + repository.update(object); + } + + @Test(expected = NotIdentifiableException.class) + public void testRemoveNoId() { + ObjectRepository repository = db.getRepository(WithOutId.class); + WithOutId object = new WithOutId(); + object.setName("name"); + object.setNumber(1L); + repository.remove(object); + } + + @Test(expected = ValidationException.class) + public void testProjectionFailedInstantiate() { + ObjectRepository repository = db.getRepository(WithOutId.class); + WithOutId object = new WithOutId(); + object.setName("name"); + object.setNumber(1L); + repository.insert(object); + + RecordStream project = repository.find().project(NitriteId.class); + assertNull(project.toList()); + } + + @Test(expected = ValidationException.class) + public void testNullInsert() { + ObjectRepository repository = db.getRepository(WithOutId.class); + repository.insert(null); + } + + @Test(expected = InvalidIdException.class) + public void testGetByNullId() { + ObjectRepository repository = db.getRepository(WithPublicField.class); + WithPublicField object = new WithPublicField(); + object.name = "test"; + object.number = 2; + + repository.insert(object); + WithPublicField instance = repository.getById(null); + assertEquals(object.name, instance.name); + assertEquals(object.number, instance.number); + } + + @Test + public void testExternalNitriteId() { + ObjectRepository repository = db.getRepository(WithNitriteId.class); + WithNitriteId obj = new WithNitriteId(); + NitriteId id = NitriteId.createId("1"); + obj.setIdField(id); + obj.setName("testExternalNitriteId"); + WriteResult result = repository.update(obj, true); + + obj = new WithNitriteId(); + id = result.iterator().next(); + obj.setIdField(id); + obj.setName("testExternalNitriteId"); + result = repository.update(obj, true); + assertNotEquals(id.getIdValue(), result.iterator().next().getIdValue()); + } + + @Test(expected = IndexingException.class) + public void testWithoutEmbeddedId() { + ObjectRepository repository = db.getRepository(WithoutEmbeddedId.class); + assertNull(repository); + } + + @Test(expected = InvalidIdException.class) + public void testGetByWrongIdType() { + ObjectRepository repository = db.getRepository(WithPublicField.class); + WithPublicField object = new WithPublicField(); + object.name = "test"; + object.number = 2; + + repository.insert(object); + + NitriteId id = NitriteId.createId("1"); + WithPublicField instance = repository.getById(id); + assertEquals(object.name, instance.name); + assertEquals(object.number, instance.number); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryTest.java new file mode 100644 index 000000000..b49f11fbd --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/ObjectRepositoryTest.java @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import com.github.javafaker.Faker; +import lombok.Data; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.meta.Attributes; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.MappableMapper; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.integration.repository.data.*; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Entity; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.util.Date; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.awaitility.Awaitility.await; +import static org.dizitart.no2.common.module.NitriteModule.module; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class ObjectRepositoryTest { + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Before + public void setUp() { + NitriteMapper mapper = new MappableMapper(); + + db = Nitrite.builder() + .loadModule(module(mapper)) + .fieldSeparator(".") + .openOrCreate(); + } + + @After + public void close() throws Exception { + db.close(); + db = null; + } + + @Test + public void testWithClassField() { + ObjectRepository repository = db.getRepository(WithClassField.class); + + WithClassField object = new WithClassField(); + object.setName("test"); + object.setClazz(String.class); + + repository.insert(object); + WithClassField instance = repository.getById("test"); + assertEquals(instance.getName(), object.getName()); + assertEquals(instance.getClazz(), object.getClazz()); + } + + @Test + public void testWithFinalField() { + ObjectRepository repository = db.getRepository(WithFinalField.class); + WithFinalField object = new WithFinalField(); + object.setName("test"); + + repository.insert(object); + for (WithFinalField instance : repository.find()) { + assertEquals(object.getName(), instance.getName()); + assertEquals(object.getNumber(), instance.getNumber()); + } + } + + @Test + public void testWithOutGetterSetter() { + ObjectRepository repository = db.getRepository(WithOutGetterSetter.class); + WithOutGetterSetter object = new WithOutGetterSetter(); + + repository.insert(object); + for (WithOutGetterSetter instance : repository.find()) { + assertEquals(object, instance); + } + } + + @Test + public void testWithOutId() { + ObjectRepository repository = db.getRepository(WithOutId.class); + WithOutId object = new WithOutId(); + object.setName("test"); + object.setNumber(2); + + repository.insert(object); + for (WithOutId instance : repository.find()) { + assertEquals(object.getName(), instance.getName()); + assertEquals(object.getNumber(), instance.getNumber()); + } + } + + @Test + public void testWithPublicField() { + ObjectRepository repository = db.getRepository(WithPublicField.class); + WithPublicField object = new WithPublicField(); + object.name = "test"; + object.number = 2; + + repository.insert(object); + WithPublicField instance = repository.getById("test"); + assertEquals(object.name, instance.name); + assertEquals(object.number, instance.number); + } + + @Test + public void testWithTransientField() { + ObjectRepository repository = db.getRepository(WithTransientField.class); + WithTransientField object = new WithTransientField(); + object.setNumber(2); + object.setName("test"); + + repository.insert(object); + WithTransientField instance = repository.getById(2L); + assertNotEquals(object.getName(), instance.getName()); + assertNull(instance.getName()); + assertEquals(object.getNumber(), instance.getNumber()); + } + + @Test + public void testWriteThousandRecords() { + int count = 5000; + + ObjectRepository repository = db.getRepository(StressRecord.class); + + for (int i = 0; i < count; i++) { + StressRecord record = new StressRecord(); + record.setFirstName(UUID.randomUUID().toString()); + record.setFailed(false); + record.setLastName(UUID.randomUUID().toString()); + record.setProcessed(false); + + repository.insert(record); + } + + Cursor cursor + = repository.find(where("failed").eq(false)); + for (StressRecord record : cursor) { + record.setProcessed(true); + repository.update(where("firstName").eq(record.getFirstName()), record); + } + } + + @Test + public void testWithPackagePrivateClass() { + ObjectRepository repository = db.getRepository(InternalClass.class); + InternalClass internalClass = new InternalClass(); + internalClass.setId(1); + internalClass.setName("name"); + + repository.insert(internalClass); + InternalClass instance = repository.getById((long) 1); + assertEquals(internalClass.getName(), instance.getName()); + assertEquals(internalClass.getId(), instance.getId()); + } + + @Test + public void testWithPrivateConstructor() { + ObjectRepository repository = + db.getRepository(WithPrivateConstructor.class); + + WithPrivateConstructor object = WithPrivateConstructor.create("test", 2L); + repository.insert(object); + for (WithPrivateConstructor instance : repository.find()) { + assertEquals(object, instance); + } + } + + @Test + public void testWithDateAsId() { + ObjectRepository repository = db.getRepository(WithDateId.class); + + WithDateId object1 = new WithDateId(); + object1.setId(new Date(1482773634L)); + object1.setName("first date"); + repository.insert(object1); + + WithDateId object2 = new WithDateId(); + object2.setName("second date"); + object2.setId(new Date(1482773720L)); + repository.insert(object2); + + assertEquals(repository.find(where("id").eq(new Date(1482773634L))) + .firstOrNull(), object1); + assertEquals(repository.find(where("id").eq(new Date(1482773720L))) + .firstOrNull(), object2); + } + + @Test + public void testWithIdInheritance() { + ObjectRepository repository = db.getRepository(ChildClass.class); + assertTrue(repository.hasIndex("id")); + assertTrue(repository.hasIndex("date")); + assertTrue(repository.hasIndex("text")); + + ChildClass childClass = new ChildClass(); + childClass.setName("first"); + childClass.setDate(new Date(100000L)); + childClass.setId(1L); + childClass.setText("I am first class"); + repository.insert(childClass); + + childClass = new ChildClass(); + childClass.setName("seconds"); + childClass.setDate(new Date(100001L)); + childClass.setId(2L); + childClass.setText("I am second class"); + repository.insert(childClass); + + childClass = new ChildClass(); + childClass.setName("third"); + childClass.setDate(new Date(100002L)); + childClass.setId(3L); + childClass.setText("I am third class"); + repository.insert(childClass); + + assertEquals(repository.find(where("text").text("class")).size(), 3); + assertEquals(repository.find(where("text").text("second")).size(), 0); // filtered in stop words + assertEquals(repository.find(where("date").eq(new Date(100000L))).size(), 1); + assertEquals(repository.find(where("id").eq(1L)).size(), 1); + } + + @Test + public void testAttributes() { + ObjectRepository repository = db.getRepository(WithDateId.class); + Attributes attributes = new Attributes(repository.getDocumentCollection().getName()); + repository.setAttributes(attributes); + assertEquals(repository.getAttributes(), attributes); + } + + @Test + public void testKeyedRepository() { + // an object repository of employees who are managers + ObjectRepository managerRepo = db.getRepository(Employee.class, "managers"); + + // an object repository of all employee + ObjectRepository employeeRepo = db.getRepository(Employee.class); + + // and object repository of employees who are developers + ObjectRepository developerRepo = db.getRepository(Employee.class, "developers"); + + Employee manager = new Employee(); + manager.setEmpId(1L); + manager.setAddress("abcd"); + manager.setJoinDate(new Date()); + + Employee developer = new Employee(); + developer.setEmpId(2L); + developer.setAddress("xyz"); + developer.setJoinDate(new Date()); + + managerRepo.insert(manager); + employeeRepo.insert(manager, developer); + developerRepo.insert(developer); + + assertTrue(db.hasRepository(Employee.class)); + assertTrue(db.hasRepository(Employee.class, "managers")); + assertTrue(db.hasRepository(Employee.class, "developers")); + + assertEquals(db.listRepositories().size(), 1); + assertEquals(db.listKeyedRepository().size(), 2); + + assertEquals(employeeRepo.find(where("address").text("abcd")).size(), 1); + assertEquals(employeeRepo.find(where("address").text("xyz")).size(), 1); + assertEquals(managerRepo.find(where("address").text("xyz")).size(), 0); + assertEquals(managerRepo.find(where("address").text("abcd")).size(), 1); + assertEquals(developerRepo.find(where("address").text("xyz")).size(), 1); + assertEquals(developerRepo.find(where("address").text("abcd")).size(), 0); + } + + @Test + public void testEntityRepository() { + ObjectRepository managerRepo = db.getRepository(EmployeeEntity.class, "managers"); + ObjectRepository employeeRepo = db.getRepository(EmployeeEntity.class); + ObjectRepository developerRepo = db.getRepository(EmployeeEntity.class, "developers"); + + managerRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); + employeeRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); + developerRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); + + boolean errored = false; + try { + NitriteCollection collection = db.getCollection("entity.employee"); + } catch (ValidationException e) { + errored = true; + } + assertTrue(errored); + + assertTrue(db.listRepositories().contains("entity.employee")); + assertEquals(db.listKeyedRepository().size(), 2); + assertEquals(db.listCollectionNames().size(), 0); + + assertTrue(managerRepo.hasIndex("firstName")); + assertTrue(managerRepo.hasIndex("lastName")); + assertTrue(employeeRepo.hasIndex("lastName")); + assertTrue(employeeRepo.hasIndex("lastName")); + + managerRepo.drop(); + assertEquals(db.listKeyedRepository().size(), 1); + } + + @Test + public void testIssue217() { + ObjectRepository employeeRepo = db.getRepository(EmployeeEntity.class); + AtomicInteger counter = new AtomicInteger(0); + employeeRepo.subscribe(eventInfo -> counter.incrementAndGet()); + + ObjectRepository employeeRepo2 = db.getRepository(EmployeeEntity.class); + employeeRepo2.insert(new EmployeeEntity()); + await().atMost(5, TimeUnit.SECONDS).until(() -> counter.get() == 1); + } + + @Data + @Entity(value = "entity.employee", indices = { + @Index(value = "firstName", type = IndexType.NON_UNIQUE), + @Index(value = "lastName", type = IndexType.NON_UNIQUE), + }) + private static class EmployeeEntity implements Mappable { + private static final Faker faker = new Faker(); + + @Id + private Long id; + private String firstName; + private String lastName; + + public EmployeeEntity() { + id = faker.number().randomNumber(); + firstName = faker.name().firstName(); + lastName = faker.name().lastName(); + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("id", id) + .put("firstName", firstName) + .put("lastName", lastName); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Long.class); + firstName = document.get("firstName", String.class); + lastName = document.get("lastName", String.class); + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/ProjectionTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/ProjectionTest.java new file mode 100644 index 000000000..a384735ad --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/ProjectionTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.dizitart.no2.integration.repository.data.SubEmployee; +import org.junit.Test; + +import java.util.Iterator; + +import static org.dizitart.no2.collection.FindOptions.skipBy; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class ProjectionTest extends BaseObjectRepositoryTest { + + @Test + public void testHasMore() { + RecordStream iterable = employeeRepository.find(skipBy(0).limit(5)) + .project(SubEmployee.class); + assertFalse(iterable.isEmpty()); + } + + @Test + public void testSize() { + RecordStream iterable = employeeRepository.find(skipBy(0).limit(5)) + .project(SubEmployee.class); + assertEquals(iterable.size(), 5); + } + + @Test + public void testToString() { + RecordStream iterable = employeeRepository.find(skipBy(0).limit(5)) + .project(SubEmployee.class); + assertNotNull(iterable.toString()); + } + + @Test(expected = InvalidOperationException.class) + public void testRemove() { + RecordStream iterable = employeeRepository.find(skipBy(0).limit(5)) + .project(SubEmployee.class); + Iterator iterator = iterable.iterator(); + if (iterator.hasNext()) { + iterator.next(); + iterator.remove(); + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/RepositoryCompoundIndexTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/RepositoryCompoundIndexTest.java new file mode 100644 index 000000000..9431d991e --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/RepositoryCompoundIndexTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.integration.repository.data.Book; +import org.dizitart.no2.integration.repository.data.BookId; +import org.junit.Test; + +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; + +/** + * @author Anindya Chatterjee + */ +public class RepositoryCompoundIndexTest extends BaseObjectRepositoryTest { + + @Test + public void testFindById() { + BookId bookId = new BookId(); + bookId.setAuthor("John Doe"); + bookId.setIsbn("123456"); + bookId.setName("Nitrite Database"); + + Book book = new Book(); + book.setBookId(bookId); + book.setDescription("Some random book description"); + book.setPrice(22.56); + book.setPublisher("My Publisher House"); + book.setTags(Arrays.asList("database", "nosql")); + + bookRepository.insert(book); + + Book bookById = bookRepository.getById(bookId); + assertEquals(bookById, book); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/RepositoryFactoryTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/RepositoryFactoryTest.java new file mode 100644 index 000000000..d29b4cf22 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/RepositoryFactoryTest.java @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.integration.TestUtil; +import org.dizitart.no2.collection.*; +import org.dizitart.no2.collection.events.CollectionEventListener; +import org.dizitart.no2.collection.meta.Attributes; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.common.concurrent.LockService; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.common.processors.Processor; +import org.dizitart.no2.repository.RepositoryFactory; +import org.dizitart.no2.store.NitriteStore; +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; + +import java.util.Collection; + +import static org.junit.Assert.assertNotNull; + +/** + * @author Anindya Chatterjee + */ +public class RepositoryFactoryTest { + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Test + public void testRepositoryFactory() { + RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); + assertNotNull(factory); + } + + @Test(expected = ValidationException.class) + public void testNullType() { + RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); + db = TestUtil.createDb(); + factory.getRepository(db.getConfig(), null, "dummy"); + } + + @Test + public void testNullCollection() { + RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); + db = TestUtil.createDb(); + factory.getRepository(db.getConfig(), DummyCollection.class, null); + } + + @Test(expected = ValidationException.class) + public void testNullContext() { + RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); + factory.getRepository(null, DummyCollection.class, "dummy"); + } + + @After + public void cleanUp() throws Exception { + if (db != null && !db.isClosed()) { + db.close(); + } + } + + private static class DummyCollection implements NitriteCollection { + + @Override + public WriteResult insert(Document document, Document... documents) { + return null; + } + + @Override + public WriteResult update(Filter filter, Document update, UpdateOptions updateOptions) { + return null; + } + + @Override + public WriteResult remove(Filter filter, boolean justOne) { + return null; + } + + @Override + public DocumentCursor find() { + return null; + } + + @Override + public DocumentCursor find(Filter filter) { + return null; + } + + @Override + public DocumentCursor find(Filter filter, FindOptions findOptions) { + return null; + } + + @Override + public Document getById(NitriteId nitriteId) { + return null; + } + + @Override + public String getName() { + return null; + } + + @Override + public void addProcessor(Processor processor) { + + } + + @Override + public void removeProcessor(Processor processor) { + + } + + @Override + public void createIndex(IndexOptions indexOptions, String... fields) { + + } + + @Override + public void rebuildIndex(String... fields) { + + } + + @Override + public Collection listIndices() { + return null; + } + + @Override + public boolean hasIndex(String... fields) { + return false; + } + + @Override + public boolean isIndexing(String... fields) { + return false; + } + + @Override + public void dropIndex(String... fields) { + + } + + @Override + public void dropAllIndices() { + + } + + @Override + public WriteResult insert(Document[] elements) { + return null; + } + + @Override + public WriteResult update(Document element, boolean insertIfAbsent) { + return null; + } + + @Override + public WriteResult remove(Document element) { + return null; + } + + @Override + public void clear() { + + } + + @Override + public void drop() { + + } + + @Override + public boolean isDropped() { + return false; + } + + @Override + public boolean isOpen() { + return false; + } + + @Override + public void close() { + + } + + @Override + public long size() { + return 0; + } + + @Override + public NitriteStore getStore() { + return null; + } + + @Override + public void subscribe(CollectionEventListener listener) { + + } + + @Override + public void unsubscribe(CollectionEventListener listener) { + + } + + @Override + public Attributes getAttributes() { + return null; + } + + @Override + public void setAttributes(Attributes attributes) { + + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/RepositoryJoinTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/RepositoryJoinTest.java new file mode 100644 index 000000000..84b60956d --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/RepositoryJoinTest.java @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import lombok.Data; +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteBuilder; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.Lookup; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Id; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.*; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.collection.FindOptions.skipBy; +import static org.dizitart.no2.filters.Filter.ALL; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +@RunWith(value = Parameterized.class) +public class RepositoryJoinTest { + @Parameterized.Parameter + public boolean isProtected = false; + + protected Nitrite db; + private ObjectRepository personRepository; + private ObjectRepository
    addressRepository; + + @Rule + public Retry retry = new Retry(3); + + @Parameterized.Parameters(name = "Protected = {0}") + public static Collection data() { + return Arrays.asList(new Object[][]{ + {false}, + {true}, + }); + } + + @Before + public void setUp() { + openDb(); + + personRepository = db.getRepository(Person.class); + addressRepository = db.getRepository(Address.class); + + for (int i = 0; i < 10; i++) { + Person person = new Person(); + person.setId(Integer.toString(i)); + person.setName("Person " + i); + personRepository.insert(person); + + Address address = new Address(); + address.setPersonId(Integer.toString(i)); + address.setStreet("Street address " + i); + addressRepository.insert(address); + + if (i == 5) { + Address address2 = new Address(); + address2.setPersonId(Integer.toString(i)); + address2.setStreet("Street address 2nd " + i); + addressRepository.insert(address2); + } + } + } + + private void openDb() { + NitriteBuilder nitriteBuilder = Nitrite.builder() + .fieldSeparator("."); + + if (isProtected) { + db = nitriteBuilder.openOrCreate("test-user1", "test-password1"); + } else { + db = nitriteBuilder.openOrCreate(); + } + } + + @After + public void clear() throws Exception { + if (personRepository != null && !personRepository.isDropped()) { + personRepository.remove(ALL); + } + + if (addressRepository != null && !addressRepository.isDropped()) { + addressRepository.remove(ALL); + } + + if (db != null) { + db.commit(); + db.close(); + } + } + + @Test + public void testJoin() { + Lookup lookup = new Lookup(); + lookup.setLocalField("id"); + lookup.setForeignField("personId"); + lookup.setTargetField("addresses"); + + RecordStream result + = personRepository.find().join(addressRepository.find(), lookup, + PersonDetails.class); + assertEquals(result.size(), 10); + + for (PersonDetails personDetails : result) { + Address[] addresses = personDetails.addresses.toArray(new Address[0]); + if (personDetails.id.equals("5")) { + assertEquals(addresses.length, 2); + } else { + assertEquals(addresses.length, 1); + assertEquals(addresses[0].personId, personDetails.getId()); + } + } + + result = personRepository.find(skipBy(0).limit(5)).join(addressRepository.find(), lookup, + PersonDetails.class); + + assertEquals(result.size(), 5); + assertFalse(result.isEmpty()); + assertNotNull(result.toString()); + } + + @Test(expected = InvalidOperationException.class) + public void testRemove() { + Lookup lookup = new Lookup(); + lookup.setLocalField("id"); + lookup.setForeignField("personId"); + lookup.setTargetField("addresses"); + + RecordStream result + = personRepository.find().join(addressRepository.find(), lookup, + PersonDetails.class); + assertEquals(result.size(), 10); + + Iterator iterator = result.iterator(); + if (iterator.hasNext()) { + iterator.next(); + iterator.remove(); + } + } + + @Data + public static class Person implements Mappable { + @Id + private NitriteId nitriteId; + private String id; + private String name; + + @Override + public Document write(NitriteMapper mapper) { + return createDocument() + .put("nitriteId", nitriteId) + .put("id", id) + .put("name", name); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + nitriteId = document.get("nitriteId", NitriteId.class); + id = document.get("id", String.class); + name = document.get("name", String.class); + } + } + + @Data + public static class Address implements Mappable { + @Id + private NitriteId nitriteId; + private String personId; + private String street; + + @Override + public Document write(NitriteMapper mapper) { + return createDocument() + .put("nitriteId", nitriteId) + .put("personId", personId) + .put("street", street); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + nitriteId = document.get("nitriteId", NitriteId.class); + personId = document.get("personId", String.class); + street = document.get("street", String.class); + } + } + + @Data + public static class PersonDetails implements Mappable { + @Id + private NitriteId nitriteId; + private String id; + private String name; + private List
    addresses; + + @Override + public Document write(NitriteMapper mapper) { + return createDocument() + .put("nitriteId", nitriteId) + .put("personId", id) + .put("street", name) + .put("addresses", addresses); + } + + @Override + @SuppressWarnings("unchecked") + public void read(NitriteMapper mapper, Document document) { + nitriteId = document.get("nitriteId", NitriteId.class); + id = document.get("id", String.class); + name = document.get("name", String.class); + Set documents = document.get("addresses", Set.class); + this.addresses = new ArrayList<>(); + for (Document doc : documents) { + Address address = new Address(); + address.read(mapper, doc); + addresses.add(address); + } + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/RepositoryModificationTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/RepositoryModificationTest.java new file mode 100644 index 000000000..90559fea1 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/RepositoryModificationTest.java @@ -0,0 +1,657 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.exceptions.InvalidIdException; +import org.dizitart.no2.exceptions.UniqueConstraintException; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.integration.repository.data.*; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.Test; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Date; +import java.util.Locale; + +import static org.awaitility.Awaitility.await; +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + + +/** + * @author Anindya Chatterjee. + */ +public class RepositoryModificationTest extends BaseObjectRepositoryTest { + + @Test + public void testCreateIndex() { + assertTrue(companyRepository.hasIndex("companyName")); + assertFalse(companyRepository.hasIndex("dateCreated")); + + companyRepository.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "dateCreated"); + assertTrue(companyRepository.hasIndex("dateCreated")); + assertFalse(companyRepository.isIndexing("dateCreated")); + } + + @Test + public void testRebuildIndex() { + companyRepository.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "dateCreated"); + assertFalse(companyRepository.isIndexing("dateCreated")); + + companyRepository.rebuildIndex("dateCreated"); + // rebuild is sync + assertFalse(companyRepository.isIndexing("dateCreated")); + + await().until(() -> !companyRepository.isIndexing("dateCreated")); + } + + @Test + public void testListIndexes() { + Collection indices = companyRepository.listIndices(); + assertEquals(indices.size(), 2); + + companyRepository.createIndex(IndexOptions.indexOptions(IndexType.NON_UNIQUE), "dateCreated"); + indices = companyRepository.listIndices(); + assertEquals(indices.size(), 3); + } + + @Test + public void testDropIndex() { + testListIndexes(); + companyRepository.dropIndex("dateCreated"); + Collection indices = companyRepository.listIndices(); + assertEquals(indices.size(), 2); + } + + @Test + public void testDropAllIndex() { + testListIndexes(); + companyRepository.dropAllIndices(); + Collection indices = companyRepository.listIndices(); + assertEquals(indices.size(), 0); + } + + @Test + public void testCompanyRecord() { + Cursor cursor = companyRepository.find(); + assertEquals(cursor.size(), 10); + assertFalse(cursor.isEmpty()); + } + + @Test + public void testInsert() { + Company company = DataGenerator.generateCompanyRecord(); + Cursor cursor = companyRepository.find(); + assertEquals(cursor.size(), 10); + + companyRepository.insert(company); + cursor = companyRepository.find(); + assertEquals(cursor.size(), 11); + + Company company1 = DataGenerator.generateCompanyRecord(); + Company company2 = DataGenerator.generateCompanyRecord(); + companyRepository.insert(new Company[]{company1, company2}); + cursor = companyRepository.find(); + assertEquals(cursor.size(), 13); + } + + @Test + public void testUpdateWithFilter() { + employeeRepository.remove(Filter.ALL); + + Employee employee = new Employee(); + employee.setCompany(null); + employee.setAddress("abcd road"); + employee.setBlob(new byte[]{1, 2, 125}); + employee.setEmpId(12L); + employee.setJoinDate(new Date()); + Note empNote = new Note(); + empNote.setNoteId(23L); + empNote.setText("sample text note"); + employee.setEmployeeNote(empNote); + + employeeRepository.insert(employee); + Cursor result = employeeRepository.find(); + assertEquals(result.size(), 1); + for (Employee e : result) { + assertEquals(e.getAddress(), "abcd road"); + } + + Employee updated = new Employee(employee); + updated.setAddress("xyz road"); + WriteResult writeResult = employeeRepository.update(where("empId").eq(12L), updated); + assertEquals(writeResult.getAffectedCount(), 1); + result = employeeRepository.find(); + assertEquals(result.size(), 1); + for (Employee e : result) { + assertEquals(e.getAddress(), "xyz road"); + } + } + + @Test + public void testUpdateWithJustOnceFalse() throws ParseException { + Date joiningDate = new Date(); + prepareUpdateWithOptions(joiningDate); + + SimpleDateFormat simpleDateFormat + = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); + Date newJoiningDate = simpleDateFormat.parse("2012-07-01T16:02:48.440Z"); + + Document updated1 = createDocument(); + updated1.put("joinDate", newJoiningDate); + + WriteResult writeResult + = employeeRepository.update(where("empId").eq(12L), updated1, false); + assertEquals(writeResult.getAffectedCount(), 1); + + Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 1); + result = employeeRepository.find(where("joinDate").eq(newJoiningDate)); + assertEquals(result.size(), 1); + + employeeRepository.remove(Filter.ALL); + prepareUpdateWithOptions(joiningDate); + result = employeeRepository.find(); + assertEquals(result.size(), 2); + + Document update = createDocument(); + update.put("joinDate", newJoiningDate); + + writeResult = employeeRepository.update(where("joinDate").eq(joiningDate), update, false); + assertEquals(writeResult.getAffectedCount(), 2); + + result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 0); + + result = employeeRepository.find(where("joinDate").eq(newJoiningDate)); + assertEquals(result.size(), 2); + } + + @Test + public void testUpsertTrue() { + Date joiningDate = new Date(); + Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 0); + + Employee employee = new Employee(); + employee.setCompany(null); + employee.setAddress("some road"); + employee.setBlob(new byte[]{1, 2, 125}); + employee.setEmpId(12L); + employee.setJoinDate(joiningDate); + Note empNote1 = new Note(); + empNote1.setNoteId(23L); + empNote1.setText("sample text note"); + employee.setEmployeeNote(empNote1); + + WriteResult writeResult + = employeeRepository.update(where("empId").eq(12), employee, true); + assertEquals(writeResult.getAffectedCount(), 1); + + result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 1); + } + + @Test + public void testUpsertFalse() { + Date joiningDate = new Date(); + Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 0); + + Employee employee = new Employee(); + employee.setCompany(null); + employee.setAddress("some road"); + employee.setBlob(new byte[]{1, 2, 125}); + employee.setEmpId(12L); + employee.setJoinDate(joiningDate); + Note empNote1 = new Note(); + empNote1.setNoteId(23L); + empNote1.setText("sample text note"); + employee.setEmployeeNote(empNote1); + + WriteResult writeResult + = employeeRepository.update(where("empId").eq(12), employee, false); + assertEquals(writeResult.getAffectedCount(), 0); + + result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 0); + } + + @Test + public void testDeleteFilterAndWithOutOption() { + Date joiningDate = new Date(); + prepareUpdateWithOptions(joiningDate); + + Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 2); + + WriteResult writeResult = employeeRepository.remove(where("joinDate").eq(joiningDate)); + assertEquals(writeResult.getAffectedCount(), 2); + result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 0); + } + + @Test + public void testDeleteFilterAndWithOption() { + Date joiningDate = new Date(); + prepareUpdateWithOptions(joiningDate); + + Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 2); + + WriteResult writeResult = employeeRepository.remove(where("joinDate").eq(joiningDate), true); + assertEquals(writeResult.getAffectedCount(), 1); + result = employeeRepository.find(where("joinDate").eq(joiningDate)); + assertEquals(result.size(), 1); + } + + @Test + public void testEmployeeRecord() { + Iterable totalResult = employeeRepository.find(); + int occurrence = 0; + for (Employee employee : totalResult) { + if (employee.getEmployeeNote().getText().toLowerCase().contains("class aptent")) { + occurrence++; + } + } + + Cursor cursor = employeeRepository.find(where("employeeNote.text").text("Class aptent")); + assertEquals(cursor.size(), occurrence); + } + + @Test + public void testUpdateWithOptions() { + Employee employee = employeeRepository.find().firstOrNull(); + + Document update = createDocument(); + update.put("address", "new address"); + + WriteResult writeResult + = employeeRepository.update(where("empId").eq(employee.getEmpId()), update, false); + assertEquals(writeResult.getAffectedCount(), 1); + + Employee byId = employeeRepository.getById(employee.getEmpId()); + assertEquals(byId.getAddress(), "new address"); + assertEquals(byId.getEmpId(), employee.getEmpId()); + + update.put("address", "another address"); + employeeRepository.update(where("empId").eq(employee.getEmpId()), update); + + byId = employeeRepository.getById(employee.getEmpId()); + assertEquals(byId.getAddress(), "another address"); + assertEquals(byId.getEmpId(), employee.getEmpId()); + } + + @Test(expected = InvalidIdException.class) + public void testMultiUpdateWithObject() { + employeeRepository.remove(Filter.ALL); + + Date now = new Date(); + Employee employee1 = new Employee(); + employee1.setEmpId(1L); + employee1.setAddress("abcd"); + employee1.setJoinDate(now); + + Employee employee2 = new Employee(); + employee2.setEmpId(2L); + employee2.setAddress("xyz"); + employee2.setJoinDate(now); + employeeRepository.insert(employee1, employee2); + + Employee update = new Employee(); + update.setAddress("new address"); + + WriteResult writeResult + = employeeRepository.update(where("joinDate").eq(now), update, false); + assertEquals(writeResult.getAffectedCount(), 0); + } + + @Test + public void testUpdateNull() { + Employee employee = employeeRepository.find().firstOrNull(); + Employee newEmployee = new Employee(employee); + newEmployee.setJoinDate(null); + + Employee result = employeeRepository.find(where("empId").eq(employee.getEmpId())).firstOrNull(); + assertNotNull(result.getJoinDate()); + + WriteResult writeResult = employeeRepository.update(newEmployee, false); + assertEquals(writeResult.getAffectedCount(), 1); + + result = employeeRepository.find(where("empId").eq(employee.getEmpId())).firstOrNull(); + assertNull(result.getJoinDate()); + + // update with object filter and item and set id different + } + + @Test + public void testUpdateWithChangedId() { + Employee employee = employeeRepository.find().firstOrNull(); + Long oldId = employee.getEmpId(); + long count = employeeRepository.size(); + + Employee newEmployee = new Employee(employee); + newEmployee.setEmpId(50L); + + Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); + assertNotNull(result.getJoinDate()); + + WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); + assertEquals(writeResult.getAffectedCount(), 1); + + assertEquals(count, employeeRepository.size()); + Cursor cursor = employeeRepository.find(where("empId").eq(oldId)); + assertEquals(cursor.size(), 0); + } + + @Test(expected = InvalidIdException.class) + public void testUpdateWithNullId() { + Employee employee = employeeRepository.find().firstOrNull(); + Long oldId = employee.getEmpId(); + + Employee newEmployee = new Employee(employee); + newEmployee.setEmpId(null); + + Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); + assertNotNull(result.getJoinDate()); + + WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); + assertEquals(writeResult.getAffectedCount(), 1); + } + + @Test(expected = UniqueConstraintException.class) + public void testUpdateWithDuplicateId() { + Employee employee = employeeRepository.find().firstOrNull(); + Long oldId = employee.getEmpId(); + long count = employeeRepository.size(); + + Employee newEmployee = new Employee(employee); + newEmployee.setEmpId(5L); + + Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); + assertNotNull(result.getJoinDate()); + + WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); + assertEquals(writeResult.getAffectedCount(), 1); + + assertEquals(count, employeeRepository.size()); + Cursor cursor = employeeRepository.find(where("empId").eq(oldId)); + assertEquals(cursor.size(), 0); + } + + @Test + public void testUpdateWithObject() { + Employee employee = employeeRepository.find().firstOrNull(); + Employee newEmployee = new Employee(employee); + + Long id = employee.getEmpId(); + String address = employee.getAddress(); + newEmployee.setAddress("new address"); + + WriteResult writeResult = employeeRepository.update(newEmployee); + assertEquals(writeResult.getAffectedCount(), 1); + + Employee emp = employeeRepository.find(where("empId").eq(id)).firstOrNull(); + assertNotEquals(address, emp.getAddress()); + assertEquals(employee.getEmpId(), emp.getEmpId()); + assertEquals(employee.getJoinDate(), emp.getJoinDate()); + assertArrayEquals(employee.getBlob(), emp.getBlob()); + } + + @Test + public void testUpsertWithObject() { + Employee employee = new Employee(); + employee.setCompany(null); + employee.setAddress("some road"); + employee.setBlob(new byte[]{1, 2, 125}); + employee.setEmpId(12L); + employee.setJoinDate(new Date()); + Note empNote = new Note(); + empNote.setNoteId(23L); + empNote.setText("sample text note"); + employee.setEmployeeNote(empNote); + + WriteResult writeResult = employeeRepository.update(employee, false); + assertEquals(writeResult.getAffectedCount(), 0); + writeResult = employeeRepository.update(employee, true); + assertEquals(writeResult.getAffectedCount(), 1); + + Employee emp = employeeRepository.find(where("empId").eq(12L)).firstOrNull(); + assertEquals(emp, employee); + } + + @Test + public void testRemoveObject() { + Employee employee = new Employee(); + employee.setCompany(null); + employee.setAddress("some road"); + employee.setBlob(new byte[]{1, 2, 125}); + employee.setEmpId(12L); + employee.setJoinDate(new Date()); + Note empNote = new Note(); + empNote.setNoteId(23L); + empNote.setText("sample text note"); + employee.setEmployeeNote(empNote); + + long size = employeeRepository.size(); + + employeeRepository.insert(employee); + assertEquals(employeeRepository.size(), size + 1); + + employeeRepository.remove(employee); + assertEquals(employeeRepository.size(), size); + + Employee emp = employeeRepository.find(where("empId").eq(12L)).firstOrNull(); + assertNull(emp); + } + + private void prepareUpdateWithOptions(Date joiningDate) { + employeeRepository.remove(Filter.ALL); + + Employee employee1 = new Employee(); + employee1.setCompany(null); + employee1.setAddress("some road"); + employee1.setBlob(new byte[]{1, 2, 125}); + employee1.setEmpId(12L); + employee1.setJoinDate(joiningDate); + Note empNote1 = new Note(); + empNote1.setNoteId(23L); + empNote1.setText("sample text note"); + employee1.setEmployeeNote(empNote1); + + Employee employee2 = new Employee(); + employee2.setCompany(null); + employee2.setAddress("other road"); + employee2.setBlob(new byte[]{10, 12, 25}); + employee2.setEmpId(2L); + employee2.setJoinDate(joiningDate); + Note empNote2 = new Note(); + empNote2.setNoteId(2L); + empNote2.setText("some random note"); + employee2.setEmployeeNote(empNote2); + + employeeRepository.insert(employee1, employee2); + Cursor result = employeeRepository.find(); + assertEquals(result.size(), 2); + for (Employee e : result.project(Employee.class)) { + assertEquals(e.getJoinDate(), joiningDate); + } + } + + @Test + public void testUpdateWithDoc() { + Note note = new Note(); + note.setNoteId(10L); + note.setText("some note text"); + + Document document = createDocument("address", "some address") + .put("employeeNote", note); + + WriteResult result = employeeRepository.update(Filter.ALL, document); + assertEquals(result.getAffectedCount(), 10); + } + + @Test + public void testDeleteIteratorNPE() { + ObjectRepository notes = db.getRepository(Note.class); + Note one = new Note(); + one.setText("Jane"); + one.setNoteId(1L); + Note two = new Note(); + two.setText("Jill"); + two.setNoteId(2L); + + notes.insert(one, two); + + WriteResult writeResult = notes.remove(where("text").eq("Pete")); + for (NitriteId id : writeResult) { + assertNotNull(id); + } + } + + @Test + public void testDelete() { + ObjectRepository repo = db.getRepository(WithNitriteId.class); + WithNitriteId one = new WithNitriteId(); + one.setName("Jane"); + repo.insert(one); + + WithNitriteId note = repo.find().firstOrNull(); + repo.remove(note); + + assertNull(repo.getById(one.idField)); + } + + /* + * Upsert Use Cases + * + * 1. Object does not exists + * a. if upsert true, it will insert + * b. if upsert false, nothing happens + * 2. Object exists + * a. if upsert true, it will update, old id remains same + * b. if upsert false, it will update, old id remains same + * + * */ + + @Test + public void testUpdateObjectNotExistsUpsertTrue() { + ObjectRepository repo = db.getRepository(InternalClass.class); + InternalClass a = new InternalClass(); + a.setId(1); + a.setName("first"); + repo.insert(a); + + a = new InternalClass(); + a.setId(2); + a.setName("second"); + + // it will insert as new object + repo.update(a, true); + assertEquals(repo.size(), 2); + } + + @Test + public void testUpdateObjectNotExistsUpsertFalse() { + ObjectRepository repo = db.getRepository(InternalClass.class); + InternalClass a = new InternalClass(); + a.setId(1); + a.setName("first"); + repo.insert(a); + + a = new InternalClass(); + a.setId(2); + a.setName("second"); + + // no changes will happen to repository + repo.update(a, false); + assertEquals(repo.size(), 1); + assertEquals(repo.find().firstOrNull().getId(), 1); + assertEquals(repo.find().firstOrNull().getName(), "first"); + } + + @Test + public void testUpdateObjectExistsUpsertTrue() { + ObjectRepository repo = db.getRepository(InternalClass.class); + InternalClass a = new InternalClass(); + a.setId(1); + a.setName("first"); + repo.insert(a); + + a = new InternalClass(); + a.setId(1); + a.setName("second"); + + // update existing object, keep id same + repo.update(a, true); + assertEquals(repo.size(), 1); + assertEquals(repo.find().firstOrNull().getId(), 1); + assertEquals(repo.find().firstOrNull().getName(), "second"); + } + + @Test + public void testUpdateObjectExistsUpsertFalse() { + ObjectRepository repo = db.getRepository(InternalClass.class); + InternalClass a = new InternalClass(); + a.setId(1); + a.setName("first"); + repo.insert(a); + + a = new InternalClass(); + a.setId(1); + a.setName("second"); + + // update existing object, keep id same + repo.update(a, false); + assertEquals(repo.size(), 1); + assertEquals(repo.find().firstOrNull().getId(), 1); + assertEquals(repo.find().firstOrNull().getName(), "second"); + } + + @Test + public void testNestedUpdate() { + Employee employee = employeeRepository.getById(1L); + assertNotNull(employee); + + Note note = employee.getEmployeeNote(); + String text = note.getText(); + assertNotNull(text); + + Document update = createDocument("employeeNote.text", "some updated text"); + WriteResult writeResult = employeeRepository.update(where("empId").eq(1L), update, true); + assertEquals(1, writeResult.getAffectedCount()); + + employee = employeeRepository.getById(1L); + assertNotNull(employee); + + note = employee.getEmployeeNote(); + assertNotNull(note); + assertNotEquals(text, note.getText()); + assertEquals("some updated text", note.getText()); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/RepositorySearchTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/RepositorySearchTest.java new file mode 100644 index 000000000..29524a7cf --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/RepositorySearchTest.java @@ -0,0 +1,609 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import lombok.Getter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.exceptions.FilterException; +import org.dizitart.no2.exceptions.InvalidIdException; +import org.dizitart.no2.exceptions.NotIdentifiableException; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.integration.repository.data.*; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.repository.ObjectRepository; +import org.junit.Test; + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.List; + +import static org.dizitart.no2.collection.FindOptions.orderBy; +import static org.dizitart.no2.collection.FindOptions.skipBy; +import static org.dizitart.no2.filters.Filter.*; +import static org.dizitart.no2.filters.FluentFilter.$; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee. + */ +public class RepositorySearchTest extends BaseObjectRepositoryTest { + @Test + public void testFindWithOptions() { + Cursor cursor = employeeRepository.find(skipBy(0).limit(1)); + assertEquals(cursor.size(), 1); + assertNotNull(cursor.firstOrNull()); + } + + @Test + public void testEmployeeProjection() { + List employeeList = employeeRepository.find().toList(); + List subEmployeeList + = employeeRepository.find().project(SubEmployee.class).toList(); + + assertNotNull(employeeList); + assertNotNull(subEmployeeList); + + assertTrue(employeeList.size() > 0); + assertTrue(subEmployeeList.size() > 0); + + assertEquals(employeeList.size(), subEmployeeList.size()); + + for (int i = 0; i < subEmployeeList.size(); i++) { + Employee employee = employeeList.get(i); + SubEmployee subEmployee = subEmployeeList.get(i); + + assertEquals(employee.getEmpId(), subEmployee.getEmpId()); + assertEquals(employee.getJoinDate(), subEmployee.getJoinDate()); + assertEquals(employee.getAddress(), subEmployee.getAddress()); + } + + Cursor cursor = employeeRepository.find(); + assertNotNull(cursor.firstOrNull()); + assertNotNull(cursor.toString()); + assertEquals(cursor.toList().size(), employeeList.size()); + assertNotNull(cursor.firstOrNull()); + assertEquals(cursor.toList().size(), employeeList.size()); + } + + @Test + public void testEmptyResultProjection() { + employeeRepository.remove(ALL); + assertNull(employeeRepository.find().firstOrNull()); + + assertNull(employeeRepository.find(where("empId").eq(-1)) + .firstOrNull()); + } + + @Test + public void testGetById() { + ObjectRepository empRepo = db.getRepository(Employee.class); + Employee e1 = DataGenerator.generateEmployee(); + Employee e2 = DataGenerator.generateEmployee(); + Employee e3 = DataGenerator.generateEmployee(); + Employee e4 = DataGenerator.generateEmployee(); + + e1.setEmpId(1000000L); + e2.setEmpId(2000000L); + e3.setEmpId(3000000L); + e4.setEmpId(4000000L); + + empRepo.insert(e1, e2, e3, e4); + + Employee byId = empRepo.getById(2000000L); + assertEquals(byId, e2); + } + + @Test(expected = NotIdentifiableException.class) + public void testGetByIdNoId() { + ObjectRepository repository = db.getRepository(Note.class); + Note n1 = DataGenerator.randomNote(); + Note n2 = DataGenerator.randomNote(); + Note n3 = DataGenerator.randomNote(); + + n1.setNoteId(1000000L); + n2.setNoteId(2000000L); + n3.setNoteId(3000000L); + + repository.insert(n1, n2, n3); + + repository.getById(2000000L); + } + + @Test(expected = InvalidIdException.class) + public void testGetByIdNullId() { + ObjectRepository empRepo = db.getRepository(Employee.class); + Employee e1 = DataGenerator.generateEmployee(); + Employee e2 = DataGenerator.generateEmployee(); + Employee e3 = DataGenerator.generateEmployee(); + Employee e4 = DataGenerator.generateEmployee(); + + e1.setEmpId(1000000L); + e2.setEmpId(2000000L); + e3.setEmpId(3000000L); + e4.setEmpId(4000000L); + + empRepo.insert(e1, e2, e3, e4); + + empRepo.getById(null); + } + + @Test(expected = InvalidIdException.class) + public void testGetByIdWrongType() { + ObjectRepository empRepo = db.getRepository(Employee.class); + Employee e1 = DataGenerator.generateEmployee(); + Employee e2 = DataGenerator.generateEmployee(); + Employee e3 = DataGenerator.generateEmployee(); + Employee e4 = DataGenerator.generateEmployee(); + + e1.setEmpId(1000000L); + e2.setEmpId(2000000L); + e3.setEmpId(3000000L); + e4.setEmpId(4000000L); + + empRepo.insert(e1, e2, e3, e4); + + Employee byId = empRepo.getById("employee"); + assertNull(byId); + } + + @Test + public void testEqualFilterById() { + Employee employee = employeeRepository.find().firstOrNull(); + long empId = employee.getEmpId(); + Employee emp = employeeRepository.find(where("empId").eq(empId)) + .project(Employee.class).firstOrNull(); + assertEquals(employee, emp); + } + + @Test + public void testEqualFilter() { + Employee employee = employeeRepository.find() + .firstOrNull(); + + Employee emp = employeeRepository.find(where("joinDate").eq(employee.getJoinDate())) + .project(Employee.class) + .firstOrNull(); + assertEquals(employee, emp); + } + + @Test + public void testStringEqualFilter() { + ObjectRepository repository = db.getRepository(ProductScore.class); + + ProductScore object = new ProductScore(); + object.setProduct("test"); + object.setScore(1); + repository.insert(object); + + object = new ProductScore(); + object.setProduct("test"); + object.setScore(2); + repository.insert(object); + + object = new ProductScore(); + object.setProduct("another-test"); + object.setScore(3); + repository.insert(object); + + assertEquals(repository.find(where("product").eq("test")).size(), 2); + } + + @Test + public void testAndFilter() { + Employee emp = employeeRepository.find().firstOrNull(); + + long id = emp.getEmpId(); + String address = emp.getAddress(); + Date joinDate = emp.getJoinDate(); + + Cursor cursor = employeeRepository.find( + and( + where("empId").eq(id), + where("address").regex(address), + where("joinDate").eq(joinDate) + ) + ); + Employee employee = cursor.firstOrNull(); + + assertEquals(emp, employee); + } + + @Test + public void testOrFilter() { + Employee emp = employeeRepository.find().firstOrNull(); + long id = emp.getEmpId(); + + Employee employee = employeeRepository.find( + or( + where("empId").eq(id), + where("address").text("n/a"), + where("joinDate").eq(null) + )).firstOrNull(); + + assertEquals(emp, employee); + } + + @Test + public void testNotFilter() { + Employee emp = employeeRepository.find().firstOrNull(); + long id = emp.getEmpId(); + + Employee employee = employeeRepository.find( + where("empId").eq(id).not()).firstOrNull(); + assertNotEquals(emp, employee); + } + + @Test + public void testGreaterFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Ascending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").gt(id)) + .toList(); + + assertFalse(employeeList.contains(emp)); + assertEquals(employeeList.size(), 9); + } + + @Test + public void testGreaterEqualFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Ascending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").gte(id)) + .toList(); + + assertTrue(employeeList.contains(emp)); + assertEquals(employeeList.size(), 10); + } + + @Test + public void testLesserThanFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Descending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").lt(id)) + .toList(); + + assertFalse(employeeList.contains(emp)); + assertEquals(employeeList.size(), 9); + } + + @Test + public void testLesserEqualFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Descending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").lte(id)) + .toList(); + + assertTrue(employeeList.contains(emp)); + assertEquals(employeeList.size(), 10); + } + + @Test + public void testTextFilter() { + Employee emp = employeeRepository.find().firstOrNull(); + String text = emp.getEmployeeNote().getText(); + + List employeeList = employeeRepository.find(where("employeeNote.text").text(text)) + .toList(); + + assertTrue(employeeList.contains(emp)); + } + + @Test + public void testRegexFilter() { + Cursor employees = employeeRepository.find(); + int count = employees.toList().size(); + + List employeeList = employeeRepository.find(where("emailAddress") + .regex("^[a-zA-Z0-9+_.-]+@[a-zA-Z0-9.-]+$")) + .toList(); + + assertEquals(employeeList.size(), count); + } + + @Test + public void testInFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Descending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").in(id, id - 1, id - 2)) + .toList(); + + assertTrue(employeeList.contains(emp)); + assertEquals(employeeList.size(), 3); + + employeeList = employeeRepository.find(where("empId").in(id - 1, id - 2)).toList(); + assertEquals(employeeList.size(), 2); + } + + @Test + public void testNotInFilter() { + Employee emp = employeeRepository.find(orderBy("empId", SortOrder.Descending)).firstOrNull(); + long id = emp.getEmpId(); + + List employeeList = employeeRepository.find(where("empId").notIn(id, id - 1, id - 2)) + .toList(); + + assertFalse(employeeList.contains(emp)); + assertEquals(employeeList.size(), 7); + + employeeList = employeeRepository.find(where("empId").notIn(id - 1, id - 2)).toList(); + assertEquals(employeeList.size(), 8); + } + + @Test + public void testElemMatchFilter() { + final ProductScore score1 = new ProductScore("abc", 10); + final ProductScore score2 = new ProductScore("abc", 8); + final ProductScore score3 = new ProductScore("abc", 7); + final ProductScore score4 = new ProductScore("xyz", 5); + final ProductScore score5 = new ProductScore("xyz", 7); + final ProductScore score6 = new ProductScore("xyz", 8); + + ObjectRepository repository = db.getRepository(ElemMatch.class); + ElemMatch e1 = new ElemMatch() {{ + setId(1); + setStrArray(new String[]{"a", "b"}); + setProductScores(new ProductScore[]{score1, score4}); + }}; + ElemMatch e2 = new ElemMatch() {{ + setId(2); + setStrArray(new String[]{"d", "e"}); + setProductScores(new ProductScore[]{score2, score5}); + }}; + ElemMatch e3 = new ElemMatch() {{ + setId(3); + setStrArray(new String[]{"a", "f"}); + setProductScores(new ProductScore[]{score3, score6}); + }}; + + repository.insert(e1, e2, e3); + + List elements = repository.find( + where("productScores").elemMatch( + where("product").eq("xyz") + .and(where("score").gte(8)))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("score").lte(8).not())).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("product").eq("xyz") + .or(where("score").gte(8)))).toList(); + assertEquals(elements.size(), 3); + + elements = repository.find( + where("productScores").elemMatch( + where("product").eq("xyz"))).toList(); + assertEquals(elements.size(), 3); + + elements = repository.find( + where("productScores").elemMatch( + where("score").gte(10))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("score").gt(8))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("score").lt(7))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("score").lte(7))).toList(); + assertEquals(elements.size(), 3); + + elements = repository.find( + where("productScores").elemMatch( + where("score").in(7, 8))).toList(); + assertEquals(elements.size(), 2); + + elements = repository.find( + where("productScores").elemMatch( + where("score").notIn(7, 8))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find( + where("productScores").elemMatch( + where("product").regex("xyz"))).toList(); + assertEquals(elements.size(), 3); + + elements = repository.find(where("strArray").elemMatch($.eq("a"))).toList(); + assertEquals(elements.size(), 2); + + elements = repository.find( + where("strArray").elemMatch( + $.eq("a") + .or($.eq("f") + .or($.eq("b"))).not())).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find(where("strArray").elemMatch($.gt("e"))).toList(); + assertEquals(elements.size(), 1); + + elements = repository.find(where("strArray").elemMatch($.gte("e"))).toList(); + assertEquals(elements.size(), 2); + + elements = repository.find(where("strArray").elemMatch($.lte("b"))).toList(); + assertEquals(elements.size(), 2); + + elements = repository.find(where("strArray").elemMatch($.lt("a"))).toList(); + assertEquals(elements.size(), 0); + + elements = repository.find(where("strArray").elemMatch($.in("a", "f"))).toList(); + assertEquals(elements.size(), 2); + + elements = repository.find(where("strArray").elemMatch($.regex("a"))).toList(); + assertEquals(elements.size(), 2); + } + + @Test + public void testFilterAll() { + ObjectRepository repository = db.getRepository(ElemMatch.class); + Cursor cursor = repository.find(ALL); + assertNotNull(cursor); + assertEquals(cursor.size(), 0); + + repository.insert(new ElemMatch()); + cursor = repository.find(ALL); + assertNotNull(cursor); + assertEquals(cursor.size(), 1); + } + + @Test(expected = FilterException.class) + public void testEqualsOnTextIndex() { + PersonEntity p1 = new PersonEntity("jhonny"); + PersonEntity p2 = new PersonEntity("jhonny"); + PersonEntity p3 = new PersonEntity("jhonny"); + + ObjectRepository repository = db.getRepository(PersonEntity.class); + repository.insert(p1); + repository.insert(p2); + repository.insert(p3); + + List sameNamePeople = repository.find(where("name").eq("jhonny")).toList(); + assertEquals(sameNamePeople.size(), 3); + + sameNamePeople = repository.find(where("name").eq("JHONNY")).toList(); + assertEquals(sameNamePeople.size(), 0); + + sameNamePeople = repository.find(where("name").text("jhonny")).toList(); + assertEquals(sameNamePeople.size(), 3); + + sameNamePeople = repository.find(where("name").text("JHONNY")).toList(); + assertEquals(sameNamePeople.size(), 3); + + sameNamePeople = repository.find(where("name").eq("jhon*")).toList(); + assertEquals(sameNamePeople.size(), 0); + + sameNamePeople = repository.find(where("name").text("jhon*")).toList(); + assertEquals(sameNamePeople.size(), 3); + } + + @Test + public void testIssue62() { + PersonEntity p1 = new PersonEntity("abcd"); + p1.setStatus("Married"); + + PersonEntity p2 = new PersonEntity("efgh"); + p2.setStatus("Married"); + + PersonEntity p3 = new PersonEntity("ijkl"); + p3.setStatus("Un-Married"); + + ObjectRepository repository = db.getRepository(PersonEntity.class); + repository.insert(p1); + repository.insert(p2); + repository.insert(p3); + + Filter married = where("status").eq("Married"); + + assertEquals(repository.find(married).size(), 2); + assertEquals(repository.find(married, orderBy("status", SortOrder.Descending)).size(), 2); + + assertEquals(repository.find(orderBy("status", SortOrder.Descending)).firstOrNull().getStatus(), "Un-Married"); + + assertEquals(repository.find(orderBy("status", SortOrder.Ascending)).size(), 3); + assertEquals(repository.find(orderBy("status", SortOrder.Ascending)).firstOrNull().getStatus(), "Married"); + } + + @Test + public void testRepeatableIndexAnnotation() { + ObjectRepository repo = db.getRepository(RepeatableIndexTest.class); + RepeatableIndexTest first = new RepeatableIndexTest(); + first.setAge(12); + first.setFirstName("fName"); + first.setLastName("lName"); + repo.insert(first); + + assertTrue(repo.hasIndex("firstName")); + assertTrue(repo.hasIndex("age")); + assertTrue(repo.hasIndex("lastName")); + + assertEquals(repo.find(where("age").eq(12)).firstOrNull(), first); + } + + @Test + public void testIdSet() { + Cursor employees = employeeRepository.find(orderBy("empId", SortOrder.Ascending)); + assertEquals(employees.size(), 10); + } + + @Test + public void testBetweenFilter() { + @Getter + class TestData implements Mappable { + private Date age; + + public TestData(Date age) { + this.age = age; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("age", age); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + age = document.get("age", Date.class); + } + } + + TestData data1 = new TestData(new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime()); + TestData data2 = new TestData(new GregorianCalendar(2021, Calendar.FEBRUARY, 12).getTime()); + TestData data3 = new TestData(new GregorianCalendar(2022, Calendar.MARCH, 13).getTime()); + TestData data4 = new TestData(new GregorianCalendar(2023, Calendar.APRIL, 14).getTime()); + TestData data5 = new TestData(new GregorianCalendar(2024, Calendar.MAY, 15).getTime()); + TestData data6 = new TestData(new GregorianCalendar(2025, Calendar.JUNE, 16).getTime()); + + ObjectRepository repository = db.getRepository(TestData.class); + repository.insert(data1, data2, data3, data4, data5, data6); + + Cursor cursor = repository.find(where("age").between( + new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), + new GregorianCalendar(2025, Calendar.JUNE, 16).getTime())); + assertEquals(cursor.size(), 6); + + cursor = repository.find(where("age").between( + new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), + new GregorianCalendar(2025, Calendar.JUNE, 16).getTime(), false)); + assertEquals(cursor.size(), 4); + + cursor = repository.find(where("age").between( + new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), + new GregorianCalendar(2025, Calendar.JUNE, 16).getTime(), false, true)); + assertEquals(cursor.size(), 5); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/UnAnnotatedObjectTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/UnAnnotatedObjectTest.java new file mode 100644 index 000000000..5ed5e452d --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/UnAnnotatedObjectTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + + +import org.dizitart.no2.common.SortOrder; +import org.dizitart.no2.integration.repository.data.ClassA; +import org.dizitart.no2.integration.repository.data.ClassC; +import org.dizitart.no2.repository.Cursor; +import org.junit.Test; + +import static org.dizitart.no2.collection.FindOptions.orderBy; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +/** + * @author Anindya Chatterjee. + */ +public class UnAnnotatedObjectTest extends BaseObjectRepositoryTest { + + @Test + public void testFind() { + Cursor cursor = aObjectRepository.find(); + assertEquals(cursor.size(), 10); + assertFalse(cursor.isEmpty()); + + aObjectRepository.createIndex("b.number"); + + cursor = aObjectRepository.find(where("b.number").eq(160).not(), + orderBy("b.number", SortOrder.Ascending).skip(0).limit(10)); + + System.out.println("Available - " + !cursor.isEmpty()); + System.out.println("Total Size - " + cursor.size()); + + Iterable findRecord = cursor.project(ClassA.class); + for (ClassA classA : findRecord) { + System.out.println(classA); + } + + cursor = aObjectRepository.find(where("b.number").eq(160).not(), + orderBy("b.number", SortOrder.Descending).skip(2).limit(7)); + + System.out.println("Available - " + !cursor.isEmpty()); + System.out.println("Total Size - " + cursor.size()); + + findRecord = cursor.project(ClassA.class); + for (ClassA classA : findRecord) { + System.out.println(classA); + } + + cursor = cObjectRepository.find(where("id").gt(900), + orderBy("id", SortOrder.Descending).skip(2).limit(7)); + System.out.println("Available - " + !cursor.isEmpty()); + System.out.println("Total Size - " + cursor.size()); + + Iterable findRecordC = cursor.project(ClassC.class); + for (ClassC classC : findRecordC) { + System.out.println(classC); + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/UniversalTextTokenizerTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/UniversalTextTokenizerTest.java new file mode 100644 index 000000000..8d19eac2a --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/UniversalTextTokenizerTest.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteBuilder; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.index.NitriteTextIndexer; +import org.dizitart.no2.index.fulltext.Languages; +import org.dizitart.no2.index.fulltext.UniversalTextTokenizer; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.Cursor; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.repository.annotations.Index; +import org.dizitart.no2.repository.annotations.Indices; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static org.dizitart.no2.integration.DbTestOperations.getRandomTempDbFile; +import static org.dizitart.no2.filters.Filter.ALL; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.common.module.NitriteModule.module; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +/** + * @author Anindya Chatterjee + */ +public class UniversalTextTokenizerTest extends BaseObjectRepositoryTest { + private final String fileName = getRandomTempDbFile(); + private ObjectRepository textRepository; + + @Before + @Override + public void setUp() { + openDb(); + + textRepository = db.getRepository(TextData.class); + + for (int i = 0; i < 10; i++) { + TextData data = new TextData(); + data.id = i; + if (i % 2 == 0) { + data.text = "তারা বলল, “এস আমরা আমাদের জন্যে এক বড় শহর বানাই| আর এমন একটি উঁচু স্তম্ভ বানাই " + + "যা আকাশ স্পর্শ করবে| তাহলে আমরা বিখ্যাত হব এবং এটা আমাদের এক সঙ্গে ধরে রাখবে| সারা পৃথিবীতে " + + "আমরা ছড়িয়ে থাকব না|”"; + } else if (i % 3 == 0) { + data.text = "部汁楽示時葉没式将場参右属。覧観将者雄日語山銀玉襲政著約域費。新意虫跡更味株付安署審完顔団。" + + "困更表転定一史賀面政巣迎文学豊税乗。白間接特時京転閉務講封新内。側流効表害場測投活聞秀職探画労。" + + "福川順式極木注美込行警検直性禁遅。土一詳非物質紙姿漢人内池銀周街躍澹二。平討聞述並時全経詳業映回作朝送恵時。"; + } else if (i % 5 == 0) { + data.text = " أقبل لسفن العالم، في أما, بـ بال أملاً الثالث،. الذود بالرّد الثالث، مع" + + " قام, كردة الضغوط الإمداد أن وصل. ٠٨٠٤ عُقر انتباه يكن قد, أن زهاء وفنلندا بال. لان ما يقوم المعاهدات," + + " بـ بخطوط استعملت عدد. صفحة لفشل ولاتّساع لم قام, في مكثّفة الكونجرس جعل, الثالث، واقتصار دون ان.\n"; + } else { + data.text = "Lorem ipsum dolor sit amet, nobis audire perpetua eu sea. Te semper causae " + + "efficiantur per. Qui affert dolorum at. Mel tale constituto interesset in."; + } + textRepository.insert(data); + } + } + + @After + @Override + public void clear() throws Exception { + if (textRepository != null && !textRepository.isDropped()) { + textRepository.remove(ALL); + } + + if (db != null) { + db.commit(); + db.close(); + } + } + + private void openDb() { + NitriteBuilder nitriteBuilder = Nitrite.builder() + .fieldSeparator("."); + + UniversalTextTokenizer tokenizer; + if (isProtected) { + tokenizer = new UniversalTextTokenizer(Languages.Bengali, Languages.Chinese, Languages.English); + } else { + tokenizer = new UniversalTextTokenizer(Languages.ALL); + } + nitriteBuilder.loadModule(module(new NitriteTextIndexer(tokenizer))); + + if (isProtected) { + db = nitriteBuilder.openOrCreate("test-user", "test-password"); + } else { + db = nitriteBuilder.openOrCreate(); + } + } + + @Test + public void testUniversalFullTextIndexing() { + Cursor cursor = textRepository.find(where("text").text("Lorem")); + assertEquals(cursor.size(), 2); + for (TextData data : cursor) { + System.out.println("Id for English text -> " + data.id); + if (data.id % 2 == 0 || data.id % 3 == 0 || data.id % 5 == 0) { + fail(); + } + } + + cursor = textRepository.find(where("text").text("শহর")); + assertEquals(cursor.size(), 5); + for (TextData data : cursor) { + System.out.println("Id for Bengali text -> " + data.id); + if (data.id % 2 != 0) { + fail(); + } + } + + cursor = textRepository.find(where("text").text("転閉")); + assertEquals(cursor.size(), 0); + cursor = textRepository.find(where("text").text("*転閉*")); + assertEquals(cursor.size(), 2); + for (TextData data : cursor) { + System.out.println("Id for Chinese text -> " + data.id); + if (data.id % 3 != 0) { + fail(); + } + } + + cursor = textRepository.find(where("text").text("أقبل")); + if (isProtected) { + assertEquals(cursor.size(), 1); + for (TextData data : cursor) { + System.out.println("Id for Arabic text -> " + data.id); + if (data.id % 5 != 0) { + fail(); + } + } + } else { + // أقبل eliminated as stop word + assertEquals(cursor.size(), 0); + } + } + + @Indices( + @Index(value = "text", type = IndexType.FULL_TEXT) + ) + public static class TextData implements Mappable { + public int id; + public String text; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("id", id) + .put("text", text); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Integer.class); + text = document.get("text", String.class); + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/Book.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/Book.java new file mode 100644 index 000000000..5a147769c --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/Book.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.repository.annotations.Entity; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +import java.util.List; + +import static org.dizitart.no2.collection.Document.createDocument; + +/** + * @author Anindya Chatterjee + */ +@Data +@Entity(value = "books", indices = { + @Index(value = "tags", type = IndexType.NON_UNIQUE), + @Index(value = "description", type = IndexType.FULL_TEXT), + @Index(value = { "price", "publisher" }) +}) +public class Book implements Mappable { + @Id(fieldName = "book_id") + private BookId bookId; + + private String publisher; + + private Double price; + + private List tags; + + private String description; + + @Override + public Document write(NitriteMapper mapper) { + return createDocument("book_id", mapper.convert(bookId, Document.class)) + .put("publisher", publisher) + .put("price", price) + .put("tags", tags) + .put("description", description); + } + + @Override + @SuppressWarnings("unchecked") + public void read(NitriteMapper mapper, Document document) { + bookId = mapper.convert(document.get("book_id"), BookId.class); + publisher = document.get("publisher", String.class); + price = document.get("price", Double.class); + tags = (List) document.get("tags", List.class); + description = document.get("description", String.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/BookId.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/BookId.java new file mode 100644 index 000000000..239b493d3 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/BookId.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Embedded; + +import static org.dizitart.no2.collection.Document.createDocument; + +/** + * @author Anindya Chatterjee + */ +@Data +public class BookId implements Mappable { + @Embedded(order = 0) + private String isbn; + + @Embedded(order = 1, fieldName = "book_name") + private String name; + + private String author; + + @Override + public Document write(NitriteMapper mapper) { + return createDocument("isbn", isbn) + .put("book_name", name) + .put("author", author); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + isbn = document.get("isbn", String.class); + name = document.get("book_name", String.class); + author = document.get("author", String.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ChildClass.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ChildClass.java new file mode 100644 index 000000000..d3c2ba644 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ChildClass.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.InheritIndices; + +/** + * @author Anindya Chatterjee + */ +@Getter +@Setter +@InheritIndices +public class ChildClass extends ParentClass { + private String name; + + @Override + public Document write(NitriteMapper mapper) { + return super.write(mapper).put("name", name); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + super.read(mapper, document); + name = document.get("name", String.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ClassA.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ClassA.java new file mode 100644 index 000000000..a8161c4e2 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ClassA.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +import java.util.UUID; + +@EqualsAndHashCode +@ToString +public class ClassA implements Mappable { + @Getter + @Setter + private ClassB b; + @Getter + @Setter + private UUID uid; + @Getter + @Setter + private String string; + @Getter + @Setter + private byte[] blob; + + public static ClassA create(int seed) { + ClassB classB = ClassB.create(seed); + ClassA classA = new ClassA(); + classA.b = classB; + classA.uid = new UUID(seed, seed + 50); + classA.string = Integer.toHexString(seed); + classA.blob = new byte[]{(byte) seed}; + return classA; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("b", b != null ? b.write(mapper) : null) + .put("uid", uid) + .put("string", string) + .put("blob", blob); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + if (document.get("b") != null) { + b = new ClassB(); + b.read(mapper, document.get("b", Document.class)); + } + uid = document.get("uid", UUID.class); + string = document.get("string", String.class); + blob = document.get("blob", byte[].class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ClassB.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ClassB.java new file mode 100644 index 000000000..a546b91e2 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ClassB.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +@EqualsAndHashCode +@ToString +class ClassB implements Comparable, Mappable { + @Getter + @Setter + private int number; + @Getter + @Setter + private String text; + + static ClassB create(int seed) { + ClassB classB = new ClassB(); + classB.setNumber(seed + 100); + classB.setText(Integer.toBinaryString(seed)); + return classB; + } + + @Override + public int compareTo(ClassB o) { + return Integer.compare(number, o.number); + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("number", number) + .put("text", text); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + number = document.get("number", Integer.class); + text = document.get("text", String.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ClassC.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ClassC.java new file mode 100644 index 000000000..860fe1e93 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ClassC.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +@EqualsAndHashCode +@ToString +public class ClassC implements Mappable { + @Getter + @Setter + private long id; + @Getter + @Setter + private double digit; + @Getter + @Setter + private ClassA parent; + + public static ClassC create(int seed) { + ClassC classC = new ClassC(); + classC.id = seed * 5000L; + classC.digit = seed * 69.65; + classC.parent = ClassA.create(seed); + return classC; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("id", id) + .put("digit", digit) + .put("parent", parent != null ? parent.write(mapper) : null); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Long.class); + digit = document.get("digit", Double.class); + if (document.get("parent") != null) { + parent = new ClassA(); + parent.read(mapper, document.get("parent", Document.class)); + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/Company.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/Company.java new file mode 100644 index 000000000..944e17358 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/Company.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; +import org.dizitart.no2.repository.annotations.Indices; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @author Anindya Chatterjee. + */ +@EqualsAndHashCode +@Indices({ + @Index(value = "companyName") +}) +public class Company implements Serializable, Mappable { + @Id(fieldName = "company_id") + @Getter + @Setter + private Long companyId; + + @Getter + @Setter + private String companyName; + + @Getter + @Setter + private Date dateCreated; + + @Getter + @Setter + private List departments; + + @Getter + @Setter + private Map> employeeRecord; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("company_id", companyId) + .put("companyName", companyName) + .put("dateCreated", dateCreated) + .put("departments", departments) + .put("employeeRecord", employeeRecord); + } + + @Override + @SuppressWarnings("unchecked") + public void read(NitriteMapper mapper, Document document) { + companyId = document.get("company_id", Long.class); + companyName = document.get("companyName", String.class); + dateCreated = document.get("dateCreated", Date.class); + departments = document.get("departments", List.class); + employeeRecord = document.get("employeeRecord", Map.class); + } + + @Override + public String toString() { + return "Company{" + + "companyId=" + companyId + + ", companyName='" + companyName + '\'' + + ", dateCreated=" + dateCreated + + ", departments=" + departments + + '}'; + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/DataGenerator.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/DataGenerator.java new file mode 100644 index 000000000..26e0dcf4a --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/DataGenerator.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import com.github.javafaker.Faker; +import lombok.val; + +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author Anindya Chatterjee. + */ +public class DataGenerator { + private static final Random random = new Random(System.currentTimeMillis()); + private static final AtomicInteger counter = new AtomicInteger(random.nextInt()); + private static final Faker faker = new Faker(random); + + private DataGenerator() {} + + public static Company generateCompanyRecord() { + Company company = new Company(); + company.setCompanyId(System.nanoTime() + counter.incrementAndGet()); + company.setCompanyName(faker.company().name()); + company.setDateCreated(faker.date().past(10, TimeUnit.DAYS)); + List departments = departments(); + company.setDepartments(departments); + + Map> employeeRecord = new HashMap<>(); + for (String department : departments) { + employeeRecord.put(department, + generateEmployeeRecords(company, random.nextInt(20))); + } + company.setEmployeeRecord(employeeRecord); + return company; + } + + private static List generateEmployeeRecords(Company company, int count) { + List employeeList = new ArrayList<>(); + for (int i = 0; i < count; i++) { + Employee employee = generateEmployee(); + employee.setCompany(company); + employeeList.add(employee); + } + return employeeList; + } + + public static Employee generateEmployee() { + Employee employee = new Employee(); + employee.setEmpId(System.nanoTime() + counter.incrementAndGet()); + employee.setJoinDate(faker.date().birthday()); + employee.setAddress(faker.address().fullAddress()); + + employee.setBlob(faker.lorem().paragraph().getBytes(StandardCharsets.UTF_8)); + employee.setEmployeeNote(randomNote()); + employee.setEmailAddress(faker.internet().emailAddress()); + + return employee; + } + + public static Note randomNote() { + Note note = new Note(); + note.setNoteId(System.nanoTime() + counter.incrementAndGet()); + note.setText(faker.lorem().paragraph()); + return note; + } + + public static Book randomBook() { + BookId bookId = new BookId(); + val bookFaker = faker.book(); + bookId.setIsbn(faker.idNumber().ssnValid()); + bookId.setAuthor(bookFaker.author()); + bookId.setName(bookFaker.title()); + + Book book = new Book(); + book.setBookId(bookId); + book.setDescription(faker.backToTheFuture().quote()); + book.setPrice(faker.number().randomDouble(2, 100, 500)); + book.setPublisher(bookFaker.publisher()); + List tags = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + tags.add(bookFaker.genre()); + } + book.setTags(tags); + return book; + } + + private static List departments() { + return new ArrayList() {{ + add("dev"); + add("hr"); + add("qa"); + add("dev-ops"); + add("sales"); + add("marketing"); + add("design"); + add("support"); + }}; + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ElemMatch.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ElemMatch.java new file mode 100644 index 000000000..cb5304e29 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ElemMatch.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Anindya Chatterjee + */ +@Data +public class ElemMatch implements Mappable { + private long id; + private String[] strArray; + private ProductScore[] productScores; + + @Override + public Document write(NitriteMapper mapper) { + List list = new ArrayList<>(); + if (productScores != null) { + for (ProductScore productScore : productScores) { + Document document = productScore.write(mapper); + list.add(document); + } + } + + return Document.createDocument("id", id) + .put("strArray", strArray) + .put("productScores", list); + } + + @Override + @SuppressWarnings("unchecked") + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Long.class); + strArray = document.get("strArray", String[].class); + List list = document.get("productScores", List.class); + if (list != null) { + productScores = new ProductScore[list.size()]; + for (int i = 0; i < list.size(); i++) { + productScores[i] = new ProductScore(); + productScores[i].read(mapper, list.get(i)); + } + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/Employee.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/Employee.java new file mode 100644 index 000000000..7204f5654 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/Employee.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author Anindya Chatterjee. + */ +@ToString +@EqualsAndHashCode +@Index(value = "joinDate", type = IndexType.NON_UNIQUE) +@Index(value = "address", type = IndexType.FULL_TEXT) +@Index(value = "employeeNote.text", type = IndexType.FULL_TEXT) +public class Employee implements Serializable, Mappable { + @Id + @Getter + @Setter + private Long empId; + + @Getter + @Setter + private Date joinDate; + + @Getter + @Setter + private String address; + + @Getter + @Setter + private String emailAddress; + + @Getter + @Setter + private transient Company company; + + @Getter + @Setter + private byte[] blob; + + @Getter + @Setter + private Note employeeNote; + + public Employee() { + } + + public Employee(Employee copy) { + empId = copy.empId; + joinDate = copy.joinDate; + address = copy.address; + company = copy.company; + blob = copy.blob; + employeeNote = copy.employeeNote; + emailAddress = copy.emailAddress; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("empId", empId) + .put("joinDate", joinDate) + .put("address", address) + .put("blob", blob) + .put("emailAddress", emailAddress) + .put("employeeNote", employeeNote != null ? employeeNote.write(mapper) : null); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + empId = document.get("empId", Long.class); + joinDate = document.get("joinDate", Date.class); + address = document.get("address", String.class); + blob = document.get("blob", byte[].class); + emailAddress = document.get("emailAddress", String.class); + + if (document.get("employeeNote") != null) { + employeeNote = new Note(); + employeeNote.read(mapper, document.get("employeeNote", Document.class)); + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/EncryptedPerson.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/EncryptedPerson.java new file mode 100644 index 000000000..8b9d4b23b --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/EncryptedPerson.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Entity; + +import java.util.Date; + +/** + * @author Anindya Chatterjee + */ +@Data +@Entity +public class EncryptedPerson implements Mappable { + private String name; + private String creditCardNumber; + private String cvv; + private Date expiryDate; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name) + .put("creditCardNumber", creditCardNumber) + .put("cvv", cvv) + .put("expiryDate", expiryDate); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + creditCardNumber = document.get("creditCardNumber", String.class); + cvv = document.get("cvv", String.class); + expiryDate = document.get("expiryDate", Date.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/Note.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/Note.java new file mode 100644 index 000000000..67dc307d1 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/Note.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +import java.io.Serializable; + +/** + * @author Anindya Chatterjee. + */ +@EqualsAndHashCode +public class Note implements Serializable, Mappable { + @Getter + @Setter + private Long noteId; + @Getter + @Setter + private String text; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument().put("noteId", noteId).put("text", text); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + noteId = document.get("noteId", Long.class); + text = document.get("text", String.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ParentClass.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ParentClass.java new file mode 100644 index 000000000..bc2514543 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ParentClass.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +import java.util.Date; + +/** + * @author Anindya Chatterjee + */ +@Getter +@Setter +@Index(value = "date") +public class ParentClass extends SuperDuperClass { + @Id + protected Long id; + private Date date; + + @Override + public Document write(NitriteMapper mapper) { + return super.write(mapper) + .put("id", id) + .put("date", date); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + super.read(mapper, document); + id = document.get("id", Long.class); + date = document.get("date", Date.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/PersonEntity.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/PersonEntity.java new file mode 100644 index 000000000..2b90075fa --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/PersonEntity.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Entity; +import org.dizitart.no2.repository.annotations.Id; +import org.dizitart.no2.repository.annotations.Index; + +import java.util.Date; +import java.util.UUID; + +/** + * @author Anindya Chatterjee + */ +@Data +@Entity(value = "MyPerson", indices = { + @Index(value = "name", type = IndexType.FULL_TEXT), + @Index(value = "status", type = IndexType.NON_UNIQUE) +}) +public class PersonEntity implements Mappable { + @Id + private String uuid; + private String name; + private String status; + private PersonEntity friend; + private Date dateCreated; + + public PersonEntity() { + this.uuid = UUID.randomUUID().toString(); + this.dateCreated = new Date(); + } + + public PersonEntity(String name) { + this.uuid = UUID.randomUUID().toString(); + this.name = name; + this.dateCreated = new Date(); + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("uuid", uuid) + .put("name", name) + .put("status", status) + .put("friend", friend != null ? friend.write(mapper) : null) + .put("dateCreated", dateCreated); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + if (document != null) { + uuid = document.get("uuid", String.class); + name = document.get("name", String.class); + status = document.get("status", String.class); + dateCreated = document.get("dateCreated", Date.class); + friend = new PersonEntity(); + friend.read(mapper, document.get("friend", Document.class)); + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ProductScore.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ProductScore.java new file mode 100644 index 000000000..65550d182 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/ProductScore.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +/** + * @author Anindya Chatterjee + */ +@Getter +@Setter +public class ProductScore implements Mappable { + private String product; + private int score; + + public ProductScore() { + } + + public ProductScore(String product, int score) { + this.product = product; + this.score = score; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("product", product) + .put("score", score); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + product = document.get("product", String.class); + score = document.get("score", Integer.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/RepeatableIndexTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/RepeatableIndexTest.java new file mode 100644 index 000000000..1ecadb243 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/RepeatableIndexTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Index; + +/** + * @author Anindya Chatterjee + */ +@Data +@Index(value = "firstName") +@Index(value = "age", type = IndexType.NON_UNIQUE) +@Index(value = "lastName", type = IndexType.FULL_TEXT) +public class RepeatableIndexTest implements Mappable { + private String firstName; + private Integer age; + private String lastName; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("firstName", firstName) + .put("age", age) + .put("lastName", lastName); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + firstName = document.get("firstName", String.class); + age = document.get("age", Integer.class); + lastName = document.get("lastName", String.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/StressRecord.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/StressRecord.java new file mode 100644 index 000000000..d1cb199c4 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/StressRecord.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class StressRecord implements Mappable { + private String firstName; + private boolean processed; + private String lastName; + private boolean failed; + private String notes; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument().put("firstName", firstName) + .put("processed", processed) + .put("lastName", lastName) + .put("failed", failed) + .put("notes", notes); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + firstName = document.get("firstName", String.class); + processed = document.get("processed", Boolean.class); + lastName = document.get("lastName", String.class); + failed = document.get("failed", Boolean.class); + notes = document.get("notes", String.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/SubEmployee.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/SubEmployee.java new file mode 100644 index 000000000..8eaa3faf1 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/SubEmployee.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +import java.util.Date; + +/** + * @author Anindya Chatterjee. + */ +@EqualsAndHashCode +public class SubEmployee implements Mappable { + @Getter + @Setter + private Long empId; + + @Getter + @Setter + private Date joinDate; + + @Getter + @Setter + private String address; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("empId", empId) + .put("joinDate", joinDate) + .put("address", address); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + empId = document.get("empId", Long.class); + joinDate = document.get("joinDate", Date.class); + address = document.get("address", String.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/SuperDuperClass.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/SuperDuperClass.java new file mode 100644 index 000000000..198f16d0c --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/SuperDuperClass.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Index; + +/** + * @author Anindya Chatterjee + */ +@Getter +@Setter +@Index(value = "text", type = IndexType.FULL_TEXT) +public class SuperDuperClass implements Mappable { + private String text; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("text", text); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + text = document.get("text", String.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithCircularReference.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithCircularReference.java new file mode 100644 index 000000000..efbb6766a --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithCircularReference.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithCircularReference { + private String name; + private WithCircularReference parent; +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithClassField.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithClassField.java new file mode 100644 index 000000000..79cafe0dc --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithClassField.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithClassField implements Mappable { + @Id + private String name; + private Class clazz; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name) + .put("clazz", clazz); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + clazz = document.get("clazz", Class.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithCustomConstructor.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithCustomConstructor.java new file mode 100644 index 000000000..bea5dabe9 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithCustomConstructor.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithCustomConstructor { + private String name; + private long number; + + public WithCustomConstructor(String name, long number) { + this.name = name; + this.number = number; + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithDateId.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithDateId.java new file mode 100644 index 000000000..229f1aaf7 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithDateId.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +import java.util.Date; + +/** + * @author Anindya Chatterjee + */ +@Getter +@Setter +@EqualsAndHashCode +public class WithDateId implements Mappable { + private Date id; + private String name; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name) + .put("id", id); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + id = document.get("id", Date.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithEmptyStringId.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithEmptyStringId.java new file mode 100644 index 000000000..a0048a6bb --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithEmptyStringId.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithEmptyStringId implements Mappable { + @Id + private String name; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithFinalField.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithFinalField.java new file mode 100644 index 000000000..05afc21e8 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithFinalField.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.exceptions.ObjectMappingException; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +/** + * @author Anindya Chatterjee. + */ +@Getter +public class WithFinalField implements Mappable { + private final long number; + @Setter + private String name; + + public WithFinalField() { + number = 2; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("name", name) + .put("number", number); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + try { + Field field = getClass().getDeclaredField("number"); + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(this, document.get("number", Long.class)); + } catch (Exception e) { + throw new ObjectMappingException("failed to set value"); + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithNitriteId.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithNitriteId.java new file mode 100644 index 000000000..2364be76d --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithNitriteId.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee + */ +@Data +public class WithNitriteId implements Mappable { + @Id + public NitriteId idField; + public String name; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("idField", idField) + .put("name", name); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + idField = document.get("idField", NitriteId.class); + name = document.get("name", String.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithNullId.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithNullId.java new file mode 100644 index 000000000..0dc3fb68b --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithNullId.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithNullId implements Mappable { + @Id + private String name; + private long number; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("name", name) + .put("number", number); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + number = document.get("number", Long.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithObjectId.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithObjectId.java new file mode 100644 index 000000000..5f00f97d4 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithObjectId.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithObjectId implements Mappable { + @Id + private WithOutId withOutId; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("withOutId", withOutId); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + withOutId = document.get("withOutId", WithOutId.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithOutGetterSetter.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithOutGetterSetter.java new file mode 100644 index 000000000..a7a2c56c9 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithOutGetterSetter.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +/** + * @author Anindya Chatterjee. + */ +@EqualsAndHashCode +public class WithOutGetterSetter implements Mappable { + private String name; + private long number; + + public WithOutGetterSetter() { + name = "test"; + number = 2; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name) + .put("number", number); + + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + number = document.get("number", Long.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithOutId.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithOutId.java new file mode 100644 index 000000000..09b63c2c2 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithOutId.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithOutId implements Comparable, Mappable { + private String name; + private long number; + + @Override + public int compareTo(WithOutId o) { + return Long.compare(number, o.number); + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("name", name) + .put("number", number); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + number = document.get("number", Long.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithPrivateConstructor.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithPrivateConstructor.java new file mode 100644 index 000000000..a425209fb --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithPrivateConstructor.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.EqualsAndHashCode; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; + +/** + * @author Anindya Chatterjee. + */ +@EqualsAndHashCode +public class WithPrivateConstructor implements Mappable { + private String name; + private long number; + + private WithPrivateConstructor() { + name = "test"; + number = 2; + } + + public static WithPrivateConstructor create(final String name, final long number) { + WithPrivateConstructor obj = new WithPrivateConstructor(); + obj.number = number; + obj.name = name; + return obj; + } + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name) + .put("number", number); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + number = document.get("number", Long.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithPublicField.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithPublicField.java new file mode 100644 index 000000000..793388231 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithPublicField.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +public class WithPublicField implements Mappable { + @Id + public String name; + public long number; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("name", name) + .put("number", number); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + name = document.get("name", String.class); + number = document.get("number", Long.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithTransientField.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithTransientField.java new file mode 100644 index 000000000..9c1ade657 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithTransientField.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Getter; +import lombok.Setter; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Getter +@Setter +public class WithTransientField implements Mappable { + private transient String name; + @Id + private long number; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("number", number); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + number = document.get("number", Long.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithoutEmbeddedId.java b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithoutEmbeddedId.java new file mode 100644 index 000000000..9ecb9a68b --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/repository/data/WithoutEmbeddedId.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.repository.data; + +import lombok.Data; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee + */ +@Data +public class WithoutEmbeddedId implements Mappable { + @Id + private NestedId nestedId; + private String data; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("nestedId", nestedId.write(mapper)) + .put("data", data); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + Document nestedId = document.get("nestedId", Document.class); + this.nestedId = mapper.convert(nestedId, NestedId.class); + this.data = document.get("data", String.class); + } + + + @Data + public static class NestedId implements Mappable { + private Long id; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument() + .put("id", id); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Long.class); + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/stream/DocumentCursorTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/stream/DocumentCursorTest.java new file mode 100644 index 000000000..ae795393c --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/stream/DocumentCursorTest.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.stream; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.DocumentCursor; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.streams.DocumentStream; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; + +import java.util.Iterator; + +import static org.dizitart.no2.integration.TestUtil.createDb; +import static org.dizitart.no2.collection.Document.createDocument; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee. + */ +public class DocumentCursorTest { + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Test + public void testFindResult() { + db = createDb(); + NitriteCollection collection = db.getCollection("test"); + collection.insert(createDocument("first", "second")); + + DocumentCursor result = collection.find(); + assertTrue(result instanceof DocumentStream); + } + + @Test(expected = InvalidOperationException.class) + public void testIteratorRemove() { + db = createDb(); + NitriteCollection collection = db.getCollection("test"); + collection.insert(createDocument("first", "second")); + + DocumentCursor cursor = collection.find(); + Iterator iterator = cursor.iterator(); + if (iterator.hasNext()) { + iterator.next(); + iterator.remove(); + } + } + + @Test + public void testValidateProjection() { + db = createDb(); + NitriteCollection collection = db.getCollection("test"); + collection.insert(createDocument("first", "second")); + + Document projection = createDocument("first", createDocument("second", null)); + RecordStream project = collection.find().project(projection); + assertNotNull(project); + } + + @After + public void cleanUp() throws Exception { + if (db != null && !db.isClosed()) { + db.close(); + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/stream/JoinedDocumentStreamTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/stream/JoinedDocumentStreamTest.java new file mode 100644 index 000000000..f8459a1ea --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/stream/JoinedDocumentStreamTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.stream; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.integration.Retry; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.common.Lookup; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.streams.JoinedDocumentStream; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; + +import java.util.Iterator; + +import static org.dizitart.no2.integration.TestUtil.createDb; +import static org.dizitart.no2.collection.Document.createDocument; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * @author Anindya Chatterjee + */ +public class JoinedDocumentStreamTest { + private Nitrite db; + + @Rule + public Retry retry = new Retry(3); + + @Test + public void testFindResult() { + db = createDb(); + NitriteCollection collection = db.getCollection("test"); + collection.insert(createDocument("first", "second")); + + RecordStream result = collection.find().join(collection.find(), new Lookup()); + assertTrue(result instanceof JoinedDocumentStream); + } + + @Test(expected = InvalidOperationException.class) + public void testIteratorRemove() { + db = createDb(); + NitriteCollection collection = db.getCollection("test"); + collection.insert(createDocument("first", "second")); + + RecordStream cursor = collection.find().join(collection.find(), new Lookup()); + assertNotNull(cursor.toString()); + Iterator iterator = cursor.iterator(); + if (iterator.hasNext()) { + iterator.next(); + iterator.remove(); + } + } + + + @After + public void cleanUp() throws Exception { + if (db != null && !db.isClosed()) { + db.close(); + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/transaction/TransactionCollectionTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/transaction/TransactionCollectionTest.java new file mode 100644 index 000000000..05a2b095b --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/transaction/TransactionCollectionTest.java @@ -0,0 +1,791 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.transaction; + +import com.github.javafaker.Faker; +import org.dizitart.no2.integration.collection.BaseCollectionTest; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.meta.Attributes; +import org.dizitart.no2.exceptions.NitriteIOException; +import org.dizitart.no2.exceptions.TransactionException; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.transaction.Session; +import org.dizitart.no2.transaction.Transaction; +import org.junit.Test; + +import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.collection.UpdateOptions.updateOptions; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class TransactionCollectionTest extends BaseCollectionTest { + + @Test + public void testCommitInsert() { + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + + Document document = createDocument("firstName", "John"); + txCol.insert(document); + + assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); + assertNotEquals(collection.find(where("firstName").eq("John")).size(), 1); + + transaction.commit(); + + assertEquals(collection.find(where("firstName").eq("John")).size(), 1); + } + } + } + + @Test + public void testRollbackInsert() { + collection.createIndex("firstName"); + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + + NitriteCollection txCol = transaction.getCollection("test"); + + Document document = createDocument("firstName", "John"); + Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); + txCol.insert(document); + txCol.insert(document2); + + // just to create UniqueConstraintViolation for rollback + collection.insert(createDocument("firstName", "Jane")); + + assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); + assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertNotEquals(collection.find(where("firstName").eq("John")).size(), 1); + assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + } + } + } + + @Test + public void testCommitUpdate() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + document.put("lastName", "Doe"); + + txCol.update(where("firstName").eq("John"), document, updateOptions(true)); + + assertEquals(txCol.find(where("lastName").eq("Doe")).size(), 1); + assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + + transaction.commit(); + + assertEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + } + } + } + + @Test + public void testRollbackUpdate() { + collection.createIndex("firstName"); + collection.insert(createDocument("firstName", "Jane")); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + + NitriteCollection txCol = transaction.getCollection("test"); + + Document document = createDocument("firstName", "John"); + Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); + txCol.update(where("firstName").eq("Jane"), document2); + txCol.insert(document); + + // just to create UniqueConstraintViolation for rollback + collection.insert(createDocument("firstName", "John")); + + assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); + assertEquals(txCol.find(where("lastName").eq("Doe")).size(), 1); + assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(collection.find(where("firstName").eq("Jane")).size(), 1); + assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + } + } + } + + @Test + public void testCommitRemove() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + + txCol.remove(where("firstName").eq("John")); + + assertEquals(txCol.find(where("firstName").eq("John")).size(), 0); + assertEquals(collection.find(where("firstName").eq("John")).size(), 1); + + transaction.commit(); + + assertEquals(collection.find(where("firstName").eq("John")).size(), 0); + } + } + } + + @Test + public void testRollbackRemove() { + collection.createIndex("firstName"); + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + NitriteCollection txCol = transaction.getCollection("test"); + + txCol.remove(where("firstName").eq("John")); + + assertEquals(txCol.find(where("firstName").eq("John")).size(), 0); + assertEquals(collection.find(where("firstName").eq("John")).size(), 1); + + txCol.insert(createDocument("firstName", "Jane")); + collection.insert(createDocument("firstName", "Jane")); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(collection.find(where("firstName").eq("John")).size(), 1); + assertEquals(collection.find(where("firstName").eq("Jane")).size(), 1); + } + } + } + + @Test + public void testCommitCreateIndex() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + txCol.createIndex(indexOptions(IndexType.FULL_TEXT), "firstName"); + + assertTrue(txCol.hasIndex("firstName")); + assertFalse(collection.hasIndex("firstName")); + + transaction.commit(); + + assertTrue(collection.hasIndex("firstName")); + } + } + } + + @Test + public void testRollbackCreateIndex() { + Document document = createDocument("firstName", "John"); + Document document2 = createDocument("firstName", "Jane"); + collection.insert(document); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + NitriteCollection txCol = transaction.getCollection("test"); + + txCol.createIndex("firstName"); + + assertTrue(txCol.hasIndex("firstName")); + assertFalse(collection.hasIndex("firstName")); + + txCol.insert(document2); + collection.insert(document2); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertFalse(collection.hasIndex("firstName")); + } + } + } + + @Test + public void testCommitClear() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + txCol.clear(); + + assertEquals(0, txCol.size()); + assertEquals(1, collection.size()); + + transaction.commit(); + + assertEquals(0, collection.size()); + } + } + } + + @Test + public void testRollbackClear() { + collection.createIndex("firstName"); + Document document = createDocument("firstName", "John"); + Document document2 = createDocument("firstName", "Jane"); + collection.insert(document); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + NitriteCollection txCol = transaction.getCollection("test"); + + txCol.clear(); + + assertEquals(0, txCol.size()); + assertEquals(1, collection.size()); + + txCol.insert(document2); + collection.insert(document2); + + throw new TransactionException("failed"); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(2, collection.size()); + } + } + } + + @Test + public void testCommitDropIndex() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + collection.createIndex("firstName"); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + txCol.dropIndex("firstName"); + + assertFalse(txCol.hasIndex("firstName")); + assertTrue(collection.hasIndex("firstName")); + + transaction.commit(); + + assertFalse(collection.hasIndex("firstName")); + } + } + } + + @Test + public void testRollbackDropIndex() { + Document document = createDocument("firstName", "John").put("lastName", "Doe"); + Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); + collection.insert(document); + collection.createIndex("firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + NitriteCollection txCol = transaction.getCollection("test"); + txCol.dropIndex("lastName"); + + assertFalse(txCol.hasIndex("lastName")); + assertTrue(collection.hasIndex("lastName")); + + txCol.insert(document2); + collection.insert(document2); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertTrue(collection.hasIndex("lastName")); + } + } + } + + @Test + public void testCommitDropAllIndices() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + collection.createIndex("firstName"); + collection.createIndex("lastName"); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + txCol.dropAllIndices(); + + assertFalse(txCol.hasIndex("firstName")); + assertFalse(txCol.hasIndex("lastName")); + assertTrue(collection.hasIndex("firstName")); + assertTrue(collection.hasIndex("lastName")); + + transaction.commit(); + + assertFalse(collection.hasIndex("firstName")); + assertFalse(collection.hasIndex("lastName")); + } + } + } + + @Test + public void testRollbackDropAllIndices() { + Document document = createDocument("firstName", "John").put("lastName", "Doe"); + collection.insert(document); + collection.createIndex("firstName"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "lastName"); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + NitriteCollection txCol = transaction.getCollection("test"); + txCol.dropAllIndices(); + + assertFalse(txCol.hasIndex("firstName")); + assertFalse(txCol.hasIndex("lastName")); + assertTrue(collection.hasIndex("firstName")); + assertTrue(collection.hasIndex("lastName")); + + txCol.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); + collection.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); + + throw new TransactionException("failed"); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertTrue(collection.hasIndex("firstName")); + assertTrue(collection.hasIndex("lastName")); + } + } + } + + @Test + public void testCommitDropCollection() { + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + txCol.drop(); + + boolean expectedException = false; + try { + assertEquals(0, txCol.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + assertEquals(1, collection.size()); + + transaction.commit(); + + expectedException = false; + try { + assertEquals(0, collection.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + } + } + } + + @Test + public void testRollbackDropCollection() { + collection.createIndex("firstName"); + Document document = createDocument("firstName", "John"); + collection.insert(document); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + NitriteCollection txCol = transaction.getCollection("test"); + + txCol.drop(); + + boolean expectedException = false; + try { + assertEquals(0, txCol.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + assertEquals(1, collection.size()); + + throw new TransactionException("failed"); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(1, collection.size()); + } + } + } + + @Test + public void testCommitSetAttribute() { + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + NitriteCollection txCol = transaction.getCollection("test"); + + Attributes attributes = new Attributes(); + Map hashMap = new HashMap<>(); + hashMap.put("key", "value"); + attributes.setAttributes(hashMap); + txCol.setAttributes(attributes); + + assertNull(collection.getAttributes()); + + transaction.commit(); + + assertEquals("value", collection.getAttributes().get("key")); + } + } + } + + @Test + public void testRollbackSetAttribute() { + collection.createIndex("firstName"); + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + + NitriteCollection txCol = transaction.getCollection("test"); + + Attributes attributes = new Attributes(); + Map map = new HashMap<>(); + map.put("key", "value"); + attributes.setAttributes(map); + txCol.setAttributes(attributes); + + txCol.insert(createDocument("firstName", "John")); + txCol.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); + + assertNull(collection.getAttributes()); + + // just to create UniqueConstraintViolation for rollback + collection.insert(createDocument("firstName", "Jane")); + + assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); + assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertNull(collection.getAttributes().get("key")); + } + } + } + + @Test + public void testConcurrentInsertAndRemove() { + NitriteCollection collection = db.getCollection("test"); + collection.createIndex(indexOptions(IndexType.NON_UNIQUE), "firstName"); + collection.createIndex("id"); + Faker faker = new Faker(); + List> futures = new ArrayList<>(); + + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + final long fi = i; + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + NitriteCollection txCol = transaction.getCollection("test"); + + for (int j = 0; j < 10; j++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("lastName", faker.name().lastName()) + .put("id", j + (fi * 10)); + txCol.insert(document); + } + + txCol.remove(where("id").eq(2 + (fi * 10))); + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(90, collection.size()); + } + } + + @Test + public void testConcurrentInsert() { + NitriteCollection collection = db.getCollection("test"); + Faker faker = new Faker(); + List> futures = new ArrayList<>(); + + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + NitriteCollection txCol = transaction.getCollection("test"); + + for (int j = 0; j < 10; j++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("lastName", faker.name().lastName()); + txCol.insert(document); + } + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(100, collection.size()); + } + } + + @Test + public void testConcurrentUpdate() { + NitriteCollection collection = db.getCollection("test"); + for (int i = 0; i < 10; i++) { + Document document = createDocument("id", i); + collection.insert(document); + } + + Faker faker = new Faker(); + List> futures = new ArrayList<>(); + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + NitriteCollection txCol = transaction.getCollection("test"); + + for (int j = 0; j < 10; j++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("lastName", faker.name().lastName()) + .put("id", j); + txCol.update(where("id").eq(j), document, updateOptions(true)); + } + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(10, collection.size()); + } + } + + @Test + public void testTransactionOnDifferentCollections() { + NitriteCollection col1 = db.getCollection("test1"); + NitriteCollection col2 = db.getCollection("test2"); + NitriteCollection col3 = db.getCollection("test3"); + col3.createIndex("id"); + + Faker faker = new Faker(); + + try(Session session = db.createSession()) { + Transaction transaction = session.beginTransaction(); + + NitriteCollection test1 = transaction.getCollection("test1"); + NitriteCollection test2 = transaction.getCollection("test2"); + NitriteCollection test3 = transaction.getCollection("test3"); + + for (int i = 0; i < 10; i++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", i); + test1.insert(document); + + document = createDocument("firstName", faker.name().firstName()) + .put("id", i + 10); + test2.insert(document); + + document = createDocument("firstName", faker.name().firstName()) + .put("id", i + 20); + test3.insert(document); + } + + assertEquals(test1.size(), 10); + assertEquals(test2.size(), 10); + assertEquals(test3.size(), 10); + + assertEquals(col1.size(), 0); + assertEquals(col2.size(), 0); + assertEquals(col3.size(), 0); + + transaction.commit(); + + assertEquals(col1.size(), 10); + assertEquals(col2.size(), 10); + assertEquals(col3.size(), 10); + } + + + Transaction transaction = null; + try (Session session = db.createSession()) { + transaction = session.beginTransaction(); + + NitriteCollection test1 = transaction.getCollection("test1"); + NitriteCollection test2 = transaction.getCollection("test2"); + NitriteCollection test3 = transaction.getCollection("test3"); + + for (int i = 0; i < 10; i++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", i + 30); + test1.insert(document); + + document = createDocument("firstName", faker.name().firstName()) + .put("id", i + 40); + test2.insert(document); + + document = createDocument("firstName", faker.name().firstName()) + .put("id", i + 50); + test3.insert(document); + } + + assertEquals(test1.size(), 20); + assertEquals(test2.size(), 20); + assertEquals(test3.size(), 20); + + assertEquals(col1.size(), 10); + assertEquals(col2.size(), 10); + assertEquals(col3.size(), 10); + + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", 52); + col3.insert(document); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + + assertEquals(col1.size(), 10); + assertEquals(col2.size(), 10); + assertEquals(col3.size(), 11); // last document added + } + } + + @Test(expected = TransactionException.class) + public void testFailureOnClosedTransaction() { + try(Session session = db.createSession()) { + Transaction transaction = session.beginTransaction(); + NitriteCollection col = transaction.getCollection("test"); + col.insert(createDocument("id", 1)); + transaction.commit(); + + col.insert(createDocument("id", 2)); + fail(); + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/transaction/TransactionRepositoryTest.java b/nitrite/src/test/java/org/dizitart/no2/integration/transaction/TransactionRepositoryTest.java new file mode 100644 index 000000000..4e506726d --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/transaction/TransactionRepositoryTest.java @@ -0,0 +1,829 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.transaction; + +import com.github.javafaker.Faker; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.meta.Attributes; +import org.dizitart.no2.exceptions.NitriteIOException; +import org.dizitart.no2.exceptions.TransactionException; +import org.dizitart.no2.index.IndexType; +import org.dizitart.no2.integration.repository.BaseObjectRepositoryTest; +import org.dizitart.no2.repository.ObjectRepository; +import org.dizitart.no2.integration.repository.data.SubEmployee; +import org.dizitart.no2.transaction.Session; +import org.dizitart.no2.transaction.Transaction; +import org.junit.Test; + +import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import static org.dizitart.no2.collection.Document.createDocument; +import static org.dizitart.no2.filters.FluentFilter.where; +import static org.dizitart.no2.index.IndexOptions.indexOptions; +import static org.junit.Assert.*; + +/** + * @author Anindya Chatterjee + */ +public class TransactionRepositoryTest extends BaseObjectRepositoryTest { + + @Test + public void testCommitInsert() { + ObjectRepository repository = db.getRepository(TxData.class); + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + TxData txData1 = new TxData(); + txData1.setId(1L); + txData1.setName("John"); + + txRepo.insert(txData1); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 1); + assertNotEquals(repository.find(where("name").eq("John")).size(), 1); + + transaction.commit(); + + assertEquals(repository.find(where("name").eq("John")).size(), 1); + } + } + } + + @Test + public void testRollbackInsert() { + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + TxData txData1 = new TxData(); + txData1.setId(1L); + txData1.setName("John"); + + TxData txData2 = new TxData(); + txData2.setId(2L); + txData2.setName("Jane"); + + txRepo.insert(txData1, txData2); + + txData2.setName("Molly"); + repository.insert(txData2); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 1); + assertEquals(repository.find(where("name").eq("John")).size(), 0); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(repository.find(where("name").eq("John")).size(), 0); + assertEquals(repository.find(where("name").eq("Molly")).size(), 1); + } + } + } + + @Test + public void testCommitUpdate() { + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(new TxData(1L, "John")); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + TxData txData1 = new TxData(1L, "Jane"); + txRepo.update(txData1, true); + + assertEquals(txRepo.find(where("name").eq("Jane")).size(), 1); + assertNotEquals(repository.find(where("name").eq("Jane")).size(), 1); + + transaction.commit(); + + assertEquals(repository.find(where("name").eq("Jane")).size(), 1); + } + } + } + + @Test + public void testRollbackUpdate() { + ObjectRepository repository = db.getRepository(TxData.class, "rollback"); + repository.createIndex("name"); + repository.insert(new TxData(1L, "Jane")); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + + ObjectRepository txRepo = transaction.getRepository(TxData.class, "rollback"); + + TxData txData1 = new TxData(); + txData1.setId(2L); + txData1.setName("John"); + + TxData txData2 = new TxData(); + txData2.setId(1L); + txData2.setName("Jane Doe"); + txRepo.update(txData2); + txRepo.insert(txData1); + + // just to create UniqueConstraintViolation for rollback + repository.insert(txData1); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 1); + assertEquals(txRepo.find(where("name").eq("Jane Doe")).size(), 1); + assertNotEquals(repository.find(where("name").eq("Jane Doe")).size(), 1); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(repository.find(where("name").eq("Jane")).size(), 1); + assertNotEquals(repository.find(where("name").eq("Jane Doe")).size(), 1); + } + } + } + + @Test + public void testCommitRemove() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + txRepo.remove(where("name").eq("John")); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 0); + assertEquals(repository.find(where("name").eq("John")).size(), 1); + + transaction.commit(); + + assertEquals(repository.find(where("name").eq("John")).size(), 0); + } + } + } + + @Test + public void testRollbackRemove() { + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + TxData txData1 = new TxData(1L, "John"); + repository.insert(txData1); + + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + txRepo.remove(where("name").eq("John")); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 0); + assertEquals(repository.find(where("name").eq("John")).size(), 1); + + TxData txData2 = new TxData(2L, "Jane"); + txRepo.insert(txData2); + repository.insert(txData2); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(repository.find(where("name").eq("John")).size(), 1); + assertEquals(repository.find(where("name").eq("Jane")).size(), 1); + } + } + } + + @Test + public void testCommitCreateIndex() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.createIndex(indexOptions(IndexType.FULL_TEXT), "name"); + + assertTrue(txRepo.hasIndex("name")); + assertFalse(repository.hasIndex("name")); + + transaction.commit(); + + assertTrue(repository.hasIndex("name")); + } + } + } + + @Test + public void testRollbackCreateIndex() { + TxData txData1 = new TxData(1L, "John"); + TxData txData2 = new TxData(2L, "Jane"); + + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(txData1); + + try(Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.createIndex(indexOptions(IndexType.FULL_TEXT), "name"); + + assertTrue(txRepo.hasIndex("name")); + assertFalse(repository.hasIndex("name")); + + txRepo.insert(txData2); + repository.insert(txData2); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertFalse(repository.hasIndex("name")); + } + } + } + + @Test + public void testCommitClear() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.clear(); + + assertEquals(0, txRepo.size()); + assertEquals(1, repository.size()); + + transaction.commit(); + + assertEquals(0, repository.size()); + } + } + } + + @Test + public void testRollbackClear() { + TxData txData1 = new TxData(1L, "John"); + TxData txData2 = new TxData(2L, "Jane"); + + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try(Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.clear(); + + assertEquals(0, txRepo.size()); + assertEquals(1, repository.size()); + + txRepo.insert(txData2); + repository.insert(txData2); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(2, repository.size()); + } + } + } + + @Test + public void testCommitDropIndex() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.dropIndex("name"); + + assertFalse(txRepo.hasIndex("name")); + assertTrue(repository.hasIndex("name")); + + transaction.commit(); + + assertFalse(repository.hasIndex("name")); + } + } + } + + @Test + public void testRollbackDropIndex() { + TxData txData1 = new TxData(1L, "John"); + TxData txData2 = new TxData(2L, "Jane"); + + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try(Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.dropIndex("name"); + + assertFalse(txRepo.hasIndex("name")); + assertTrue(repository.hasIndex("name")); + + txRepo.insert(txData2); + repository.insert(txData2); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertTrue(repository.hasIndex("name")); + } + } + } + + @Test + public void testCommitDropAllIndices() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.dropAllIndices(); + + assertFalse(txRepo.hasIndex("name")); + assertTrue(repository.hasIndex("name")); + + transaction.commit(); + + assertFalse(repository.hasIndex("name")); + } + } + } + + @Test + public void testRollbackDropAllIndices() { + TxData txData1 = new TxData(1L, "John"); + TxData txData2 = new TxData(2L, "Jane"); + + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try(Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.dropAllIndices(); + + assertFalse(txRepo.hasIndex("name")); + assertTrue(repository.hasIndex("name")); + + txRepo.insert(txData2); + repository.insert(txData2); + + throw new TransactionException("failed"); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertTrue(repository.hasIndex("name")); + } + } + } + + @Test + public void testCommitDropRepository() { + TxData txData1 = new TxData(1L, "John"); + ObjectRepository repository = db.getRepository(TxData.class); + repository.insert(txData1); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.drop(); + + boolean expectedException = false; + try { + assertEquals(0, txRepo.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + assertEquals(1, repository.size()); + + transaction.commit(); + + expectedException = false; + try { + assertEquals(0, repository.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + } + } + } + + @Test + public void testRollbackDropRepository() { + TxData txData1 = new TxData(1L, "John"); + + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + repository.insert(txData1); + + try(Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.drop(); + + boolean expectedException = false; + try { + assertEquals(0, txRepo.size()); + } catch (NitriteIOException e) { + expectedException = true; + } + assertTrue(expectedException); + assertEquals(1, repository.size()); + + throw new TransactionException("failed"); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertEquals(1, repository.size()); + } + } + } + + @Test + public void testCommitSetAttribute() { + ObjectRepository repository = db.getRepository(TxData.class); + + try (Session session = db.createSession()) { + try (Transaction transaction = session.beginTransaction()) { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + Attributes attributes = new Attributes(); + Map hashMap = new HashMap<>(); + hashMap.put("key", "value"); + attributes.setAttributes(hashMap); + txRepo.setAttributes(attributes); + + assertNull(repository.getAttributes()); + + transaction.commit(); + + assertEquals("value", repository.getAttributes().get("key")); + } + } + } + + @Test + public void testRollbackSetAttribute() { + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex("name"); + try (Session session = db.createSession()) { + Transaction transaction = null; + try { + transaction = session.beginTransaction(); + + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + Attributes attributes = new Attributes(); + Map map = new HashMap<>(); + map.put("key", "value"); + attributes.setAttributes(map); + txRepo.setAttributes(attributes); + + txRepo.insert(new TxData(1L, "John")); + txRepo.insert(new TxData(2L, "Jane")); + + assertNull(repository.getAttributes()); + + // just to create UniqueConstraintViolation for rollback + repository.insert(new TxData(2L, "Jane")); + + assertEquals(txRepo.find(where("name").eq("John")).size(), 1); + assertNotEquals(repository.find(where("name").eq("John")).size(), 1); + + transaction.commit(); + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + assertNull(repository.getAttributes().get("key")); + } + } + } + + @Test + public void testConcurrentInsertAndRemove() { + ObjectRepository repository = db.getRepository(TxData.class); + repository.createIndex(indexOptions(IndexType.NON_UNIQUE), "name"); + Faker faker = new Faker(); + List> futures = new ArrayList<>(); + + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + final long fi = i; + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + for (long j = 0; j < 10; j++) { + TxData txData = new TxData(j + (fi * 10), faker.name().name()); + txRepo.insert(txData); + } + + txRepo.remove(where("id").eq(2L + (fi * 10))); + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(90, repository.size()); + } + } + + @Test + public void testConcurrentInsert() { + ObjectRepository repository = db.getRepository(TxData.class); + Faker faker = new Faker(); + List> futures = new ArrayList<>(); + + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + final long fi = i; + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + for (long j = 0; j < 10; j++) { + TxData txData = new TxData(j + (fi * 10), faker.name().name()); + txRepo.insert(txData); + } + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(100, repository.size()); + } + } + + @Test + public void testConcurrentUpdate() { + ObjectRepository repository = db.getRepository(TxData.class); + Faker faker = new Faker(); + for (long j = 0; j < 10; j++) { + TxData txData = new TxData(j, faker.name().name()); + repository.insert(txData); + } + + List> futures = new ArrayList<>(); + try (Session session = db.createSession()) { + ExecutorService executorService = Executors.newCachedThreadPool(); + for (int i = 0; i < 10; i++) { + Future future = executorService.submit(() -> { + Transaction transaction = session.beginTransaction(); + try { + ObjectRepository txRepo = transaction.getRepository(TxData.class); + + for (int j = 0; j < 10; j++) { + TxData txData = new TxData((long) j, faker.name().name()); + txRepo.update(where("id").eq(j), txData); + } + + transaction.commit(); + } catch (Exception e) { + e.printStackTrace(); + transaction.rollback(); + } finally { + transaction.close(); + } + }); + + futures.add(future); + } + + futures.forEach(future -> { + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + }); + + assertEquals(10, repository.size()); + } + } + + @Test + public void testTransactionOnDifferentRepositoriesAndCollections() { + ObjectRepository repo1 = db.getRepository(TxData.class); + ObjectRepository repo2 = db.getRepository(TxData.class, "2"); + ObjectRepository repo3 = db.getRepository(SubEmployee.class); + NitriteCollection col1 = db.getCollection("test1"); + col1.createIndex("id"); + + Faker faker = new Faker(); + + try(Session session = db.createSession()) { + Transaction transaction = session.beginTransaction(); + + ObjectRepository txRepo1 = transaction.getRepository(TxData.class); + ObjectRepository txRepo2 = transaction.getRepository(TxData.class, "2"); + ObjectRepository txRepo3 = transaction.getRepository(SubEmployee.class); + NitriteCollection test1 = transaction.getCollection("test1"); + + for (long i = 0; i < 10; i++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", i); + test1.insert(document); + + TxData txData1 = new TxData(i, faker.name().name()); + txRepo1.insert(txData1); + + TxData txData2 = new TxData(i + 10, faker.name().name()); + txRepo2.insert(txData2); + + SubEmployee employee = new SubEmployee(); + employee.setAddress(faker.address().fullAddress()); + employee.setEmpId(i); + employee.setJoinDate(faker.date().birthday()); + txRepo3.insert(employee); + } + + assertEquals(test1.size(), 10); + assertEquals(txRepo1.size(), 10); + assertEquals(txRepo2.size(), 10); + assertEquals(txRepo3.size(), 10); + + assertEquals(col1.size(), 0); + assertEquals(repo1.size(), 0); + assertEquals(repo2.size(), 0); + assertEquals(repo3.size(), 0); + + transaction.commit(); + + assertEquals(col1.size(), 10); + assertEquals(repo1.size(), 10); + assertEquals(repo2.size(), 10); + assertEquals(repo3.size(), 10); + } + + Transaction transaction = null; + try (Session session = db.createSession()) { + transaction = session.beginTransaction(); + + ObjectRepository txRepo1 = transaction.getRepository(TxData.class); + ObjectRepository txRepo2 = transaction.getRepository(TxData.class, "2"); + ObjectRepository txRepo3 = transaction.getRepository(SubEmployee.class); + NitriteCollection test1 = transaction.getCollection("test1"); + + for (long i = 0; i < 10; i++) { + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", i + 10); + test1.insert(document); + + TxData txData1 = new TxData(i + 10, faker.name().name()); + txRepo1.insert(txData1); + + TxData txData2 = new TxData(i + 20, faker.name().name()); + txRepo2.insert(txData2); + + SubEmployee employee = new SubEmployee(); + employee.setAddress(faker.address().fullAddress()); + employee.setEmpId(i + 10); + employee.setJoinDate(faker.date().birthday()); + txRepo3.insert(employee); + } + + assertEquals(test1.size(), 20); + assertEquals(txRepo1.size(), 20); + assertEquals(txRepo2.size(), 20); + assertEquals(txRepo3.size(), 20); + + assertEquals(col1.size(), 10); + assertEquals(repo1.size(), 10); + assertEquals(repo2.size(), 10); + assertEquals(repo3.size(), 10); + + Document document = createDocument("firstName", faker.name().firstName()) + .put("id", 12L); + col1.insert(document); + + transaction.commit(); + + fail(); + } catch (TransactionException e) { + assert transaction != null; + transaction.rollback(); + + assertEquals(col1.size(), 11); // last doc added + assertEquals(repo1.size(), 10); + assertEquals(repo2.size(), 10); + assertEquals(repo3.size(), 10); + } + } + + @Test(expected = TransactionException.class) + public void testFailureOnClosedTransaction() { + try(Session session = db.createSession()) { + Transaction transaction = session.beginTransaction(); + ObjectRepository txRepo = transaction.getRepository(TxData.class); + txRepo.insert(new TxData(1L, "John")); + transaction.commit(); + + txRepo.insert(new TxData(2L, "Jane")); + fail(); + } + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/integration/transaction/TxData.java b/nitrite/src/test/java/org/dizitart/no2/integration/transaction/TxData.java new file mode 100644 index 000000000..1e5ed7ca6 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/integration/transaction/TxData.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.integration.transaction; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; +import org.dizitart.no2.repository.annotations.Id; + +/** + * @author Anindya Chatterjee. + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +class TxData implements Mappable { + @Id + private Long id; + private String name; + + @Override + public Document write(NitriteMapper mapper) { + return Document.createDocument("id", id) + .put("name", name); + } + + @Override + public void read(NitriteMapper mapper, Document document) { + id = document.get("id", Long.class); + name = document.get("name", String.class); + } +} diff --git a/nitrite/src/test/java/org/dizitart/no2/mapper/Company.java b/nitrite/src/test/java/org/dizitart/no2/mapper/Company.java deleted file mode 100644 index 79dbec25a..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/mapper/Company.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapper; - -import lombok.Data; -import org.dizitart.no2.collection.Document; - -import java.io.Serializable; - -/** - * @author Anindya Chatterjee. - */ -@Data -public class Company implements Mappable { - private String name; - private Long id; - private CompanyId companyId; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("id", id) - .put("name", name) - .put("companyId", mapper.convert(companyId, Document.class)); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - id = document.get("id", Long.class); - companyId = document.get("companyId", CompanyId.class); - } - - @Data - public static class CompanyId implements Comparable, Serializable, Mappable { - private Long idValue; - - public CompanyId(long value) { - this.idValue = value; - } - - @Override - public int compareTo(CompanyId other) { - return idValue.compareTo(other.idValue); - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument().put("idValue", idValue); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - idValue = document.get("idValue", Long.class); - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/mapper/Employee.java b/nitrite/src/test/java/org/dizitart/no2/mapper/Employee.java deleted file mode 100644 index d1dfd1a9f..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/mapper/Employee.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.mapper; - -import lombok.Data; -import lombok.ToString; -import org.dizitart.no2.collection.Document; - -import java.util.Date; - -/** - * @author Anindya Chatterjee - */ -@Data -@ToString -public class Employee implements Mappable { - private String empId; - private String name; - private Date joiningDate; - private Employee boss; - - @Override - public Document write(NitriteMapper mapper) { - Document document = Document.createDocument("empId", getEmpId()) - .put("name", getName()) - .put("joiningDate", getJoiningDate()); - - if (getBoss() != null) { - document.put("boss", mapper.convert(getBoss(), Document.class)); - } - return document; - } - - @Override - public void read(NitriteMapper mapper, Document document) { - setEmpId(document.get("empId", String.class)); - setName(document.get("name", String.class)); - setJoiningDate(document.get("joiningDate", Date.class)); - - Document bossDoc = document.get("boss", Document.class); - if (bossDoc != null) { - Employee boss = mapper.convert(bossDoc, Employee.class); - setBoss(boss); - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/migration/InstructionTypeTest.java b/nitrite/src/test/java/org/dizitart/no2/migration/InstructionTypeTest.java new file mode 100644 index 000000000..6b0fdb25c --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/migration/InstructionTypeTest.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.migration; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class InstructionTypeTest { + + @Test + public void testValueOf() { + assertEquals(InstructionType.AddPassword, InstructionType.valueOf("AddPassword")); + } + + @Test + public void testValues() { + assertEquals(21, InstructionType.values().length); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/migration/MigrationStepTest.java b/nitrite/src/test/java/org/dizitart/no2/migration/MigrationStepTest.java new file mode 100644 index 000000000..dfc0d8feb --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/migration/MigrationStepTest.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.migration; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class MigrationStepTest { + @Test + public void testConstructor() { + MigrationStep actualMigrationStep = new MigrationStep(); + actualMigrationStep.setArguments("Arguments"); + actualMigrationStep.setInstructionType(InstructionType.AddPassword); + assertEquals(InstructionType.AddPassword, actualMigrationStep.getInstructionType()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/migration/NitriteInstructionsTest.java b/nitrite/src/test/java/org/dizitart/no2/migration/NitriteInstructionsTest.java new file mode 100644 index 000000000..0b1e7c621 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/migration/NitriteInstructionsTest.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.migration; + +import org.junit.Test; + +import java.util.LinkedList; + +import static org.junit.Assert.assertSame; + +public class NitriteInstructionsTest { + @Test + public void testConstructor() { + LinkedList migrationStepList = new LinkedList<>(); + assertSame(migrationStepList, (new NitriteInstructions(migrationStepList)).getMigrationSteps()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/migration/commands/AddFieldTest.java b/nitrite/src/test/java/org/dizitart/no2/migration/commands/AddFieldTest.java new file mode 100644 index 000000000..73ca7a5fa --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/migration/commands/AddFieldTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.migration.commands; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.store.memory.InMemoryStore; +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class AddFieldTest { + @Test + public void testExecute() { + AddField addField = new AddField("Collection Name", "Field Name", "Default Value"); + NitriteConfig nitriteConfig = mock(NitriteConfig.class); + doReturn(new InMemoryStore()).when(nitriteConfig).getNitriteStore(); + Nitrite nitrite = mock(Nitrite.class); + when(nitrite.getConfig()).thenReturn(nitriteConfig); + InMemoryStore inMemoryStore = new InMemoryStore(); + doReturn(inMemoryStore).when(nitrite).getStore(); + addField.execute(nitrite); + verify(nitrite).getConfig(); + verify(nitrite).getStore(); + verify(nitriteConfig).getNitriteStore(); + NitriteMap nitriteMap = addField.nitriteMap; + assertTrue(nitriteMap instanceof org.dizitart.no2.store.memory.InMemoryMap); + assertSame(inMemoryStore, addField.nitriteStore); + assertNull(nitriteMap.getAttributes()); + assertTrue(nitriteMap.isEmpty()); + assertEquals("Collection Name", nitriteMap.getName()); + assertEquals(0L, addField.operations.getSize()); + } + + @Test + public void testExecute2() { + AddField addField = new AddField("Collection Name", "Field Name", "Default Value"); + NitriteConfig nitriteConfig = mock(NitriteConfig.class); + doReturn(new InMemoryStore()).when(nitriteConfig).getNitriteStore(); + Nitrite nitrite = mock(Nitrite.class); + when(nitrite.getConfig()).thenReturn(nitriteConfig); + InMemoryStore inMemoryStore = new InMemoryStore(); + doReturn(inMemoryStore).when(nitrite).getStore(); + addField.execute(nitrite); + verify(nitrite).getConfig(); + verify(nitrite).getStore(); + verify(nitriteConfig).getNitriteStore(); + NitriteMap nitriteMap = addField.nitriteMap; + assertTrue(nitriteMap instanceof org.dizitart.no2.store.memory.InMemoryMap); + assertSame(inMemoryStore, addField.nitriteStore); + assertNull(nitriteMap.getAttributes()); + assertTrue(nitriteMap.isEmpty()); + assertEquals("Collection Name", nitriteMap.getName()); + assertEquals(0L, addField.operations.getSize()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/migration/commands/ChangeDataTypeTest.java b/nitrite/src/test/java/org/dizitart/no2/migration/commands/ChangeDataTypeTest.java new file mode 100644 index 000000000..80b0c42fc --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/migration/commands/ChangeDataTypeTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.migration.commands; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.migration.TypeConverter; +import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.store.memory.InMemoryStore; +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class ChangeDataTypeTest { + @Test + public void testExecute() { + ChangeDataType changeDataType = new ChangeDataType("Collection Name", "Field Name", mock(TypeConverter.class)); + NitriteConfig nitriteConfig = mock(NitriteConfig.class); + doReturn(new InMemoryStore()).when(nitriteConfig).getNitriteStore(); + Nitrite nitrite = mock(Nitrite.class); + when(nitrite.getConfig()).thenReturn(nitriteConfig); + InMemoryStore inMemoryStore = new InMemoryStore(); + doReturn(inMemoryStore).when(nitrite).getStore(); + changeDataType.execute(nitrite); + verify(nitrite).getConfig(); + verify(nitrite).getStore(); + verify(nitriteConfig).getNitriteStore(); + NitriteMap nitriteMap = changeDataType.nitriteMap; + assertTrue(nitriteMap instanceof org.dizitart.no2.store.memory.InMemoryMap); + assertSame(inMemoryStore, changeDataType.nitriteStore); + assertNull(nitriteMap.getAttributes()); + assertTrue(nitriteMap.isEmpty()); + assertEquals("Collection Name", nitriteMap.getName()); + assertEquals(0L, changeDataType.operations.getSize()); + } + + @Test + public void testExecute2() { + ChangeDataType changeDataType = new ChangeDataType("Collection Name", "Field Name", mock(TypeConverter.class)); + NitriteConfig nitriteConfig = mock(NitriteConfig.class); + doReturn(new InMemoryStore()).when(nitriteConfig).getNitriteStore(); + Nitrite nitrite = mock(Nitrite.class); + when(nitrite.getConfig()).thenReturn(nitriteConfig); + InMemoryStore inMemoryStore = new InMemoryStore(); + doReturn(inMemoryStore).when(nitrite).getStore(); + changeDataType.execute(nitrite); + verify(nitrite).getConfig(); + verify(nitrite).getStore(); + verify(nitriteConfig).getNitriteStore(); + NitriteMap nitriteMap = changeDataType.nitriteMap; + assertTrue(nitriteMap instanceof org.dizitart.no2.store.memory.InMemoryMap); + assertSame(inMemoryStore, changeDataType.nitriteStore); + assertNull(nitriteMap.getAttributes()); + assertTrue(nitriteMap.isEmpty()); + assertEquals("Collection Name", nitriteMap.getName()); + assertEquals(0L, changeDataType.operations.getSize()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/migration/commands/DeleteFieldTest.java b/nitrite/src/test/java/org/dizitart/no2/migration/commands/DeleteFieldTest.java new file mode 100644 index 000000000..ed65a16d1 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/migration/commands/DeleteFieldTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.migration.commands; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.store.memory.InMemoryStore; +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class DeleteFieldTest { + @Test + public void testExecute() { + DeleteField deleteField = new DeleteField("Collection Name", "Field Name"); + NitriteConfig nitriteConfig = mock(NitriteConfig.class); + doReturn(new InMemoryStore()).when(nitriteConfig).getNitriteStore(); + Nitrite nitrite = mock(Nitrite.class); + when(nitrite.getConfig()).thenReturn(nitriteConfig); + InMemoryStore inMemoryStore = new InMemoryStore(); + doReturn(inMemoryStore).when(nitrite).getStore(); + deleteField.execute(nitrite); + verify(nitrite).getConfig(); + verify(nitrite).getStore(); + verify(nitriteConfig).getNitriteStore(); + NitriteMap nitriteMap = deleteField.nitriteMap; + assertTrue(nitriteMap instanceof org.dizitart.no2.store.memory.InMemoryMap); + assertSame(inMemoryStore, deleteField.nitriteStore); + assertNull(nitriteMap.getAttributes()); + assertTrue(nitriteMap.isEmpty()); + assertEquals("Collection Name", nitriteMap.getName()); + assertEquals(0L, deleteField.operations.getSize()); + } + + @Test + public void testExecute2() { + DeleteField deleteField = new DeleteField("Collection Name", "Field Name"); + NitriteConfig nitriteConfig = mock(NitriteConfig.class); + doReturn(new InMemoryStore()).when(nitriteConfig).getNitriteStore(); + Nitrite nitrite = mock(Nitrite.class); + when(nitrite.getConfig()).thenReturn(nitriteConfig); + InMemoryStore inMemoryStore = new InMemoryStore(); + doReturn(inMemoryStore).when(nitrite).getStore(); + deleteField.execute(nitrite); + verify(nitrite).getConfig(); + verify(nitrite).getStore(); + verify(nitriteConfig).getNitriteStore(); + NitriteMap nitriteMap = deleteField.nitriteMap; + assertTrue(nitriteMap instanceof org.dizitart.no2.store.memory.InMemoryMap); + assertSame(inMemoryStore, deleteField.nitriteStore); + assertNull(nitriteMap.getAttributes()); + assertTrue(nitriteMap.isEmpty()); + assertEquals("Collection Name", nitriteMap.getName()); + assertEquals(0L, deleteField.operations.getSize()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/migration/commands/RenameFieldTest.java b/nitrite/src/test/java/org/dizitart/no2/migration/commands/RenameFieldTest.java new file mode 100644 index 000000000..f28d18d49 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/migration/commands/RenameFieldTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.migration.commands; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.store.memory.InMemoryStore; +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class RenameFieldTest { + @Test + public void testExecute() { + RenameField renameField = new RenameField("Collection Name", "Old Name", "New Name"); + NitriteConfig nitriteConfig = mock(NitriteConfig.class); + doReturn(new InMemoryStore()).when(nitriteConfig).getNitriteStore(); + Nitrite nitrite = mock(Nitrite.class); + when(nitrite.getConfig()).thenReturn(nitriteConfig); + InMemoryStore inMemoryStore = new InMemoryStore(); + doReturn(inMemoryStore).when(nitrite).getStore(); + renameField.execute(nitrite); + verify(nitrite, times(2)).getConfig(); + verify(nitrite).getStore(); + verify(nitriteConfig, times(2)).getNitriteStore(); + NitriteMap nitriteMap = renameField.nitriteMap; + assertTrue(nitriteMap instanceof org.dizitart.no2.store.memory.InMemoryMap); + assertSame(inMemoryStore, renameField.nitriteStore); + assertNull(nitriteMap.getAttributes()); + assertTrue(nitriteMap.isEmpty()); + assertEquals("Collection Name", nitriteMap.getName()); + assertEquals(0L, renameField.operations.getSize()); + } + + @Test + public void testExecute2() { + RenameField renameField = new RenameField("Collection Name", "Old Name", "New Name"); + NitriteConfig nitriteConfig = mock(NitriteConfig.class); + doReturn(new InMemoryStore()).when(nitriteConfig).getNitriteStore(); + Nitrite nitrite = mock(Nitrite.class); + when(nitrite.getConfig()).thenReturn(nitriteConfig); + InMemoryStore inMemoryStore = new InMemoryStore(); + doReturn(inMemoryStore).when(nitrite).getStore(); + renameField.execute(nitrite); + verify(nitrite, times(2)).getConfig(); + verify(nitrite).getStore(); + verify(nitriteConfig, times(2)).getNitriteStore(); + NitriteMap nitriteMap = renameField.nitriteMap; + assertTrue(nitriteMap instanceof org.dizitart.no2.store.memory.InMemoryMap); + assertSame(inMemoryStore, renameField.nitriteStore); + assertNull(nitriteMap.getAttributes()); + assertTrue(nitriteMap.isEmpty()); + assertEquals("Collection Name", nitriteMap.getName()); + assertEquals(0L, renameField.operations.getSize()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/AnnotationScannerTest.java b/nitrite/src/test/java/org/dizitart/no2/repository/AnnotationScannerTest.java new file mode 100644 index 000000000..615c43162 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/repository/AnnotationScannerTest.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.repository; + +import org.dizitart.no2.NitriteBuilderTest; +import org.dizitart.no2.collection.NitriteCollection; +import org.junit.Test; + +import java.lang.reflect.Field; + +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.mock; + +public class AnnotationScannerTest { + @Test + public void testConstructor() { + Class type = Object.class; + assertNull((new AnnotationScanner(type, null, new NitriteBuilderTest.CustomNitriteMapper())).getObjectIdField()); + } + + @Test + public void testCreateIndices() { + Class type = Object.class; + AnnotationScanner annotationScanner = new AnnotationScanner(type, null, + new NitriteBuilderTest.CustomNitriteMapper()); + annotationScanner.createIndices(); + assertNull(annotationScanner.getObjectIdField()); + } + + @Test + public void testCreateIdIndex() { + Class type = Object.class; + AnnotationScanner annotationScanner = new AnnotationScanner(type, null, + new NitriteBuilderTest.CustomNitriteMapper()); + annotationScanner.createIdIndex(); + assertNull(annotationScanner.getObjectIdField()); + } + + @Test + public void testScanIndices() { + Class type = Object.class; + AnnotationScanner annotationScanner = new AnnotationScanner(type, null, + new NitriteBuilderTest.CustomNitriteMapper()); + annotationScanner.scanIndices(); + assertNull(annotationScanner.getObjectIdField()); + } + + @Test + public void testScanIndices2() { + Class type = Field.class; + AnnotationScanner annotationScanner = new AnnotationScanner(type, null, + new NitriteBuilderTest.CustomNitriteMapper()); + annotationScanner.scanIndices(); + assertNull(annotationScanner.getObjectIdField()); + } + + @Test + public void testScanIndices3() { + Class type = Object.class; + NitriteCollection collection = mock(NitriteCollection.class); + AnnotationScanner annotationScanner = new AnnotationScanner(type, collection, + new NitriteBuilderTest.CustomNitriteMapper()); + annotationScanner.scanIndices(); + assertNull(annotationScanner.getObjectIdField()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/BaseObjectRepositoryTest.java b/nitrite/src/test/java/org/dizitart/no2/repository/BaseObjectRepositoryTest.java deleted file mode 100644 index 4194cab7e..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/BaseObjectRepositoryTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.Retry; -import org.dizitart.no2.repository.data.*; -import org.junit.After; -import org.junit.Before; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Collection; - -import static org.dizitart.no2.filters.Filter.ALL; - -@RunWith(value = Parameterized.class) -public abstract class BaseObjectRepositoryTest { - @Parameterized.Parameter - public boolean isProtected = false; - - protected Nitrite db; - protected ObjectRepository companyRepository; - protected ObjectRepository employeeRepository; - protected ObjectRepository aObjectRepository; - protected ObjectRepository cObjectRepository; - -// @Rule - public Retry retry = new Retry(3); - - @Parameterized.Parameters(name = "Protected = {0}") - public static Collection data() { - return Arrays.asList(new Object[][]{ - {false}, - {true}, - }); - } - - @Before - public void setUp() { - openDb(); - - companyRepository = db.getRepository(Company.class); - employeeRepository = db.getRepository(Employee.class); - - aObjectRepository = db.getRepository(ClassA.class); - cObjectRepository = db.getRepository(ClassC.class); - - for (int i = 0; i < 10; i++) { - Company company = DataGenerator.generateCompanyRecord(); - companyRepository.insert(company); - Employee employee = DataGenerator.generateEmployee(); - employee.setEmpId((long) i + 1); - employeeRepository.insert(employee); - - aObjectRepository.insert(ClassA.create(i + 50)); - cObjectRepository.insert(ClassC.create(i + 30)); - } - } - - private void openDb() { - NitriteBuilder nitriteBuilder = Nitrite.builder() - .fieldSeparator("."); - - if (isProtected) { - db = nitriteBuilder.openOrCreate("test-user", "test-password"); - } else { - db = nitriteBuilder.openOrCreate(); - } - } - - @After - public void clear() throws IOException { - if (companyRepository != null && !companyRepository.isDropped()) { - companyRepository.remove(ALL); - } - - if (employeeRepository != null && !employeeRepository.isDropped()) { - employeeRepository.remove(ALL); - } - - if (aObjectRepository != null && !aObjectRepository.isDropped()) { - aObjectRepository.remove(ALL); - } - - if (cObjectRepository != null && !cObjectRepository.isDropped()) { - cObjectRepository.remove(ALL); - } - - if (db != null && !db.isClosed()) { - db.commit(); - db.close(); - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/CustomFieldSeparatorTest.java b/nitrite/src/test/java/org/dizitart/no2/repository/CustomFieldSeparatorTest.java deleted file mode 100644 index a84e215bf..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/CustomFieldSeparatorTest.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteConfig; -import org.dizitart.no2.Retry; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; -import org.dizitart.no2.repository.data.Company; -import org.dizitart.no2.repository.data.Note; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.Serializable; -import java.util.Date; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; - -/** - * @author Anindya Chatterjee - */ -public class CustomFieldSeparatorTest { - private Nitrite db; - private ObjectRepository repository; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - db = Nitrite.builder() - .fieldSeparator(":") - .openOrCreate(); - - repository = db.getRepository(EmployeeForCustomSeparator.class); - } - - @After - public void reset() { - (new NitriteConfig()).fieldSeparator("."); - if (db != null && !db.isClosed()) { - db.close(); - } - } - - @Test - public void testFieldSeparator() { - assertEquals(NitriteConfig.getFieldSeparator(), ":"); - } - - @Test - public void testFindByEmbeddedField() { - EmployeeForCustomSeparator employee = new EmployeeForCustomSeparator(); - employee.setCompany(new Company()); - employee.setEmployeeNote(new Note()); - - employee.setEmpId(123L); - employee.setJoinDate(new Date()); - employee.setBlob(new byte[0]); - employee.setAddress("Dummy address"); - - employee.getCompany().setCompanyId(987L); - employee.getCompany().setCompanyName("Dummy Company"); - employee.getCompany().setDateCreated(new Date()); - - employee.getEmployeeNote().setNoteId(567L); - employee.getEmployeeNote().setText("Dummy Note"); - - repository.insert(employee); - - assertEquals(repository.find(where("employeeNote.text").eq("Dummy Note")).size(), 0); - assertEquals(repository.find(where("employeeNote:text").text("Dummy Note")).size(), 1); - - assertEquals(repository.find(where("company.companyName").eq("Dummy Company")).size(), 0); - assertEquals(repository.find(where("company:companyName").eq("Dummy Company")).size(), 1); - } - - @ToString - @EqualsAndHashCode - @Indices({ - @Index(value = "joinDate", type = IndexType.NonUnique), - @Index(value = "address", type = IndexType.Fulltext), - @Index(value = "employeeNote:text", type = IndexType.Fulltext) - }) - public static class EmployeeForCustomSeparator implements Serializable, Mappable { - @Id - @Getter - @Setter - private Long empId; - - @Getter - @Setter - private Date joinDate; - - @Getter - @Setter - private String address; - - @Getter - @Setter - private Company company; - - @Getter - @Setter - private byte[] blob; - - @Getter - @Setter - private Note employeeNote; - - EmployeeForCustomSeparator() { - } - - public EmployeeForCustomSeparator(EmployeeForCustomSeparator copy) { - empId = copy.empId; - joinDate = copy.joinDate; - address = copy.address; - company = copy.company; - blob = copy.blob; - employeeNote = copy.employeeNote; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument().put("empId", empId) - .put("joinDate", joinDate) - .put("address", address) - .put("blob", blob) - .put("company", company.write(mapper)) - .put("employeeNote", employeeNote.write(mapper)); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - empId = document.get("empId", Long.class); - joinDate = document.get("joinDate", Date.class); - address = document.get("address", String.class); - blob = document.get("blob", byte[].class); - employeeNote = new Note(); - Document doc = document.get("employeeNote", Document.class); - employeeNote.read(mapper, doc); - company = new Company(); - doc = document.get("company", Document.class); - company.read(mapper, doc); - } - } - -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/DefaultObjectRepositoryTest.java b/nitrite/src/test/java/org/dizitart/no2/repository/DefaultObjectRepositoryTest.java new file mode 100644 index 000000000..726cce323 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/repository/DefaultObjectRepositoryTest.java @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.repository; + +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.FindOptions; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.collection.events.CollectionEventListener; +import org.dizitart.no2.collection.meta.Attributes; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.common.processors.ProcessorChain; +import org.dizitart.no2.common.streams.DocumentStream; +import org.dizitart.no2.common.tuples.Pair; +import org.dizitart.no2.exceptions.ValidationException; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexDescriptor; +import org.dizitart.no2.index.IndexOptions; +import org.dizitart.no2.store.memory.InMemoryStore; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class DefaultObjectRepositoryTest { + @Test + public void testAddProcessor() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + doNothing().when(nitriteCollection).addProcessor(any()); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + defaultObjectRepository.addProcessor(new ProcessorChain()); + verify(nitriteCollection).addProcessor(any()); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testRemoveProcessor() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + doNothing().when(nitriteCollection).removeProcessor(any()); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + defaultObjectRepository.removeProcessor(new ProcessorChain()); + verify(nitriteCollection).removeProcessor(any()); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testCreateIndex() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + doNothing().when(nitriteCollection).createIndex(any(), any()); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + defaultObjectRepository.createIndex(IndexOptions.indexOptions("Index Type"), "foo", "foo", "foo"); + verify(nitriteCollection).createIndex(any(), any()); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testRebuildIndex() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + doNothing().when(nitriteCollection).rebuildIndex(any()); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + defaultObjectRepository.rebuildIndex("foo", "foo", "foo"); + verify(nitriteCollection).rebuildIndex(any()); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testListIndices() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + ArrayList indexDescriptorList = new ArrayList<>(); + when(nitriteCollection.listIndices()).thenReturn(indexDescriptorList); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + Collection actualListIndicesResult = defaultObjectRepository.listIndices(); + assertSame(indexDescriptorList, actualListIndicesResult); + assertTrue(actualListIndicesResult.isEmpty()); + verify(nitriteCollection).listIndices(); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testHasIndex() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + when(nitriteCollection.hasIndex(any())).thenReturn(true); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + assertTrue(defaultObjectRepository.hasIndex("foo", "foo", "foo")); + verify(nitriteCollection).hasIndex(any()); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testIsIndexing() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + when(nitriteCollection.isIndexing(any())).thenReturn(true); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + assertTrue(defaultObjectRepository.isIndexing("foo", "foo", "foo")); + verify(nitriteCollection).isIndexing(any()); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testDropIndex() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + doNothing().when(nitriteCollection).dropIndex(any()); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + defaultObjectRepository.dropIndex("foo", "foo", "foo"); + verify(nitriteCollection).dropIndex(any()); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testDropAllIndices() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + doNothing().when(nitriteCollection).dropAllIndices(); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + defaultObjectRepository.dropAllIndices(); + verify(nitriteCollection).dropAllIndices(); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testInsert() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + when(nitriteCollection.insert(any())).thenReturn(mock(WriteResult.class)); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + defaultObjectRepository.insert(new Object[]{}); + verify(nitriteCollection).insert(any()); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testUpdate2() { + DefaultObjectRepository defaultObjectRepository = (DefaultObjectRepository) mock( + DefaultObjectRepository.class); + when(defaultObjectRepository.update(any(), (Object) any(), anyBoolean())).thenReturn(null); + defaultObjectRepository.update(mock(Filter.class), "Update", true); + verify(defaultObjectRepository).update(any(), (Object) any(), anyBoolean()); + } + + @Test + public void testRemove2() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + when(nitriteCollection.remove(any(), anyBoolean())).thenReturn(mock(WriteResult.class)); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + defaultObjectRepository.remove(mock(Filter.class), true); + verify(nitriteCollection).remove(any(), anyBoolean()); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testClear() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + doNothing().when(nitriteCollection).clear(); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + defaultObjectRepository.clear(); + verify(nitriteCollection).clear(); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testFind() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + RecordStream> recordStream = (RecordStream>) mock( + RecordStream.class); + when(nitriteCollection.find(any(), any())) + .thenReturn(new DocumentStream(recordStream, new ProcessorChain())); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + Filter filter = mock(Filter.class); + assertNull(defaultObjectRepository.find(filter, new FindOptions()).getFindPlan()); + verify(nitriteCollection).find(any(), any()); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testDrop() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + doNothing().when(nitriteCollection).drop(); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + defaultObjectRepository.drop(); + verify(nitriteCollection).drop(); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testIsDropped() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + when(nitriteCollection.isDropped()).thenReturn(true); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + assertTrue(defaultObjectRepository.isDropped()); + verify(nitriteCollection).isDropped(); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testIsOpen() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + when(nitriteCollection.isOpen()).thenReturn(true); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + assertTrue(defaultObjectRepository.isOpen()); + verify(nitriteCollection).isOpen(); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testClose() throws Exception { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + doNothing().when(nitriteCollection).close(); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + defaultObjectRepository.close(); + verify(nitriteCollection).close(); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testSize() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + when(nitriteCollection.size()).thenReturn(1L); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + assertEquals(1L, defaultObjectRepository.size()); + verify(nitriteCollection).size(); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testGetStore() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + InMemoryStore inMemoryStore = new InMemoryStore(); + doReturn(inMemoryStore).when(nitriteCollection).getStore(); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + assertSame(inMemoryStore, defaultObjectRepository.getStore()); + verify(nitriteCollection).getStore(); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testSubscribe() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + doNothing().when(nitriteCollection).subscribe(any()); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + defaultObjectRepository.subscribe(mock(CollectionEventListener.class)); + verify(nitriteCollection).subscribe(any()); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testUnsubscribe() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + doNothing().when(nitriteCollection).unsubscribe(any()); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + defaultObjectRepository.unsubscribe(mock(CollectionEventListener.class)); + verify(nitriteCollection).unsubscribe(any()); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test + public void testGetAttributes() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + Attributes attributes = new Attributes(); + when(nitriteCollection.getAttributes()).thenReturn(attributes); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + assertSame(attributes, defaultObjectRepository.getAttributes()); + verify(nitriteCollection).getAttributes(); + assertNull(defaultObjectRepository.getStore()); + } + + @Test + public void testSetAttributes() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + doNothing().when(nitriteCollection).setAttributes(any()); + Class type = Object.class; + DefaultObjectRepository defaultObjectRepository = new DefaultObjectRepository<>(type, + nitriteCollection, new NitriteConfig()); + defaultObjectRepository.setAttributes(new Attributes()); + verify(nitriteCollection).setAttributes(any()); + assertNull(defaultObjectRepository.getAttributes()); + } + + @Test(expected = ValidationException.class) + public void testConstructor() { + Class type = Object.class; + NitriteConfig nitriteConfig = new NitriteConfig(); + new DefaultObjectRepository<>(type, null, nitriteConfig); + assertTrue(nitriteConfig.getMigrations().isEmpty()); + assertEquals(1, nitriteConfig.getSchemaVersion().intValue()); + assertNull(nitriteConfig.getNitriteStore()); + } + + @Test + public void testConstructor2() { + Class forNameResult = Object.class; + NitriteCollection collection = mock(NitriteCollection.class); + DefaultObjectRepository actualDefaultObjectRepository = new DefaultObjectRepository<>(forNameResult, + collection, new NitriteConfig()); + assertNull(actualDefaultObjectRepository.getAttributes()); + assertSame(forNameResult, actualDefaultObjectRepository.getType()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/IndexValidatorTest.java b/nitrite/src/test/java/org/dizitart/no2/repository/IndexValidatorTest.java new file mode 100644 index 000000000..0c812ed53 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/repository/IndexValidatorTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.repository; + +import org.dizitart.no2.NitriteBuilderTest; +import org.dizitart.no2.exceptions.IndexingException; +import org.junit.Test; + +import java.lang.reflect.Field; + +import static org.junit.Assert.assertThrows; + +public class IndexValidatorTest { + + @Test + public void testValidate() { + IndexValidator indexValidator = new IndexValidator(new Reflector()); + Class fieldType = Object.class; + assertThrows(IndexingException.class, + () -> indexValidator.validate(fieldType, "Field", new NitriteBuilderTest.CustomNitriteMapper())); + } + + @Test + public void testValidate3() { + IndexValidator indexValidator = new IndexValidator(new Reflector()); + Class fieldType = Field.class; + assertThrows(IndexingException.class, + () -> indexValidator.validate(fieldType, "Field", new NitriteBuilderTest.CustomNitriteMapper())); + } + + @Test + public void testValidate4() { + IndexValidator indexValidator = new IndexValidator(new Reflector()); + Class fieldType = Object.class; + assertThrows(IndexingException.class, () -> indexValidator.validate(fieldType, "invalid type specified ", + new NitriteBuilderTest.CustomNitriteMapper())); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/InternalClass.java b/nitrite/src/test/java/org/dizitart/no2/repository/InternalClass.java deleted file mode 100644 index a23f1736c..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/InternalClass.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Data -class InternalClass implements Mappable { - @Id - private long id; - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("id", id) - .put("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Long.class); - name = document.get("name", String.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/NitriteIdAsIdTest.java b/nitrite/src/test/java/org/dizitart/no2/repository/NitriteIdAsIdTest.java deleted file mode 100644 index c00be30ad..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/NitriteIdAsIdTest.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.Retry; -import org.dizitart.no2.TestUtil; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.common.util.Iterables; -import org.dizitart.no2.exceptions.InvalidIdException; -import org.dizitart.no2.repository.data.WithNitriteId; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * @author Anindya Chatterjee - */ -public class NitriteIdAsIdTest { - private Nitrite db; - private ObjectRepository repo; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void before() { - db = TestUtil.createDb(); - repo = db.getRepository(WithNitriteId.class); - } - - @After - public void after() { - db.close(); - } - - @Test - public void testNitriteIdField() { - WithNitriteId item1 = new WithNitriteId(); - item1.name = "first"; - - WithNitriteId item2 = new WithNitriteId(); - item2.name = "second"; - - repo.insert(item1, item2); - - Cursor cursor = repo.find(); - for (WithNitriteId withNitriteId : cursor) { - System.out.println(withNitriteId.name); - assertNotNull(withNitriteId.idField); - } - - WithNitriteId withNitriteId = cursor.firstOrNull(); - withNitriteId.name = "third"; - - NitriteId id = withNitriteId.idField; - repo.update(withNitriteId); - - WithNitriteId byId = repo.getById(id); - assertEquals(withNitriteId, byId); - assertEquals(repo.size(), 2); - } - - @Test(expected = InvalidIdException.class) - public void setIdDuringInsert() { - WithNitriteId item1 = new WithNitriteId(); - item1.name = "first"; - item1.idField = NitriteId.newId(); - - repo.insert(item1); - } - - @Test - public void changeIdDuringUpdate() { - WithNitriteId item2 = new WithNitriteId(); - item2.name = "second"; - WriteResult result = repo.insert(item2); - NitriteId nitriteId = Iterables.firstOrNull(result); - WithNitriteId byId = repo.getById(nitriteId); - byId.idField = NitriteId.newId(); - - result = repo.update(byId); - assertEquals(result.getAffectedCount(), 0); - assertEquals(repo.size(), 1); - } - -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/ObjectCursorTest.java b/nitrite/src/test/java/org/dizitart/no2/repository/ObjectCursorTest.java index b5b17c593..b2edd5e3e 100644 --- a/nitrite/src/test/java/org/dizitart/no2/repository/ObjectCursorTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/repository/ObjectCursorTest.java @@ -1,53 +1,109 @@ /* - * Copyright (c) 2017-2020. Nitrite author or authors. + * Copyright (c) 2017-2021 Nitrite author or authors. * * Licensed 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 + * 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.dizitart.no2.repository; +import com.fasterxml.jackson.databind.util.ArrayIterator; +import org.dizitart.no2.NitriteBuilderTest; +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.Lookup; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.mapper.MappableMapper; +import org.dizitart.no2.common.processors.ProcessorChain; +import org.dizitart.no2.common.streams.DocumentStream; +import org.dizitart.no2.common.tuples.Pair; import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.repository.data.Employee; import org.junit.Test; -import java.util.AbstractCollection; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; -/** - * @author Anindya Chatterjee - */ -public class ObjectCursorTest extends BaseObjectRepositoryTest { +public class ObjectCursorTest { + @Test + public void testSize() { + RecordStream> recordStream = (RecordStream>) mock( + RecordStream.class); + Pair pair = new Pair<>(); + Pair pair1 = new Pair<>(); + when(recordStream.iterator()).thenReturn( + new ArrayIterator>(new Pair[]{pair, pair1, new Pair()})); + DocumentStream cursor = new DocumentStream(recordStream, new ProcessorChain()); + NitriteBuilderTest.CustomNitriteMapper nitriteMapper = new NitriteBuilderTest.CustomNitriteMapper(); + ObjectCursor objectCursor = new ObjectCursor<>(nitriteMapper, cursor, Object.class); + assertEquals(3L, objectCursor.size()); + verify(recordStream).iterator(); + assertTrue(objectCursor.toList().isEmpty()); + } - @Test(expected = ValidationException.class) - public void testProjectForInterface() { - Cursor cursor = employeeRepository.find(); - cursor.project(Comparable.class); + @Test + public void testConstructor() { + NitriteBuilderTest.CustomNitriteMapper nitriteMapper = new NitriteBuilderTest.CustomNitriteMapper(); + RecordStream> recordStream = (RecordStream>) mock( + RecordStream.class); + DocumentStream cursor = new DocumentStream(recordStream, new ProcessorChain()); + assertNull((new ObjectCursor<>(nitriteMapper, cursor, Object.class)).getFindPlan()); } - @Test(expected = ValidationException.class) - public void testProjectForPrimitive() { - Cursor cursor = employeeRepository.find(); - cursor.project(int.class); + @Test + public void testGetFindPlan() { + NitriteBuilderTest.CustomNitriteMapper nitriteMapper = new NitriteBuilderTest.CustomNitriteMapper(); + RecordStream> recordStream = (RecordStream>) mock( + RecordStream.class); + DocumentStream cursor = new DocumentStream(recordStream, new ProcessorChain()); + assertNull((new ObjectCursor<>(nitriteMapper, cursor, Object.class)).getFindPlan()); } - @Test(expected = ValidationException.class) - public void testProjectForArray() { - Cursor cursor = employeeRepository.find(); - cursor.project(String[].class); + @Test + public void testProject() { + NitriteBuilderTest.CustomNitriteMapper nitriteMapper = new NitriteBuilderTest.CustomNitriteMapper(); + RecordStream> recordStream = (RecordStream>) mock( + RecordStream.class); + DocumentStream cursor = new DocumentStream(recordStream, new ProcessorChain()); + ObjectCursor objectCursor = new ObjectCursor<>(nitriteMapper, cursor, Object.class); + assertThrows(ValidationException.class, () -> objectCursor.project(Object.class)); } - @Test(expected = ValidationException.class) - public void testProjectForAbstractClass() { - Cursor cursor = employeeRepository.find(); - cursor.project(AbstractCollection.class); + @Test + public void testProject3() { + Class forNameResult = Object.class; + Class forNameResult1 = Object.class; + MappableMapper nitriteMapper = new MappableMapper(forNameResult, forNameResult1, Object.class); + RecordStream> recordStream = (RecordStream>) mock( + RecordStream.class); + DocumentStream cursor = new DocumentStream(recordStream, new ProcessorChain()); + ObjectCursor objectCursor = new ObjectCursor<>(nitriteMapper, cursor, Object.class); + assertThrows(ValidationException.class, () -> objectCursor.project(Object.class)); + } + + @Test + public void testJoin() { + NitriteBuilderTest.CustomNitriteMapper nitriteMapper = new NitriteBuilderTest.CustomNitriteMapper(); + RecordStream> recordStream = (RecordStream>) mock( + RecordStream.class); + DocumentStream cursor = new DocumentStream(recordStream, new ProcessorChain()); + ObjectCursor objectCursor = new ObjectCursor<>(nitriteMapper, cursor, Object.class); + NitriteBuilderTest.CustomNitriteMapper nitriteMapper1 = new NitriteBuilderTest.CustomNitriteMapper(); + RecordStream> recordStream1 = (RecordStream>) mock( + RecordStream.class); + DocumentStream cursor1 = new DocumentStream(recordStream1, new ProcessorChain()); + ObjectCursor foreignCursor = new ObjectCursor<>(nitriteMapper1, cursor1, Object.class); + Lookup lookup = new Lookup(); + assertTrue(objectCursor.join(foreignCursor, lookup, Object.class) instanceof MutatedObjectStream); } } + diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/ObjectIdFieldTest.java b/nitrite/src/test/java/org/dizitart/no2/repository/ObjectIdFieldTest.java new file mode 100644 index 000000000..0e37591de --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/repository/ObjectIdFieldTest.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.repository; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; + +public class ObjectIdFieldTest { + @Test + public void testConstructor() { + ObjectIdField actualObjectIdField = new ObjectIdField(); + assertNull(actualObjectIdField.getField()); + assertFalse(actualObjectIdField.isEmbedded()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/ObjectRepositoryNegativeTest.java b/nitrite/src/test/java/org/dizitart/no2/repository/ObjectRepositoryNegativeTest.java deleted file mode 100644 index 020889637..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/ObjectRepositoryNegativeTest.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.Retry; -import org.dizitart.no2.TestUtil; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.*; -import org.dizitart.no2.repository.data.*; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; - -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class ObjectRepositoryNegativeTest { - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - db = TestUtil.createDb(); - } - - @After - public void close() throws IOException { - db.close(); - db = null; - } - - @Test(expected = ObjectMappingException.class) - public void testWithCircularReference() { - ObjectRepository repository = db.getRepository(WithCircularReference.class); - - WithCircularReference parent = new WithCircularReference(); - parent.setName("parent"); - WithCircularReference object = new WithCircularReference(); - object.setName("test"); - object.setParent(parent); - // circular reference - parent.setParent(object); - - WriteResult result = repository.insert(object); - for (NitriteId id : result) { - WithCircularReference instance = repository.getById(id); - assertEquals(instance.getName(), object.getName()); - assertEquals(instance.getParent().getName(), object.getParent().getName()); - } - } - - @Test(expected = ObjectMappingException.class) - public void testWithCustomConstructor() { - ObjectRepository repository = db.getRepository(WithCustomConstructor.class); - - WithCustomConstructor object = new WithCustomConstructor("test", 2L); - - WriteResult result = repository.insert(object); - for (NitriteId id : result) { - WithCustomConstructor instance = repository.getById(id); - assertEquals(object.getName(), instance.getName()); - assertEquals(object.getNumber(), instance.getNumber()); - } - } - - @Test(expected = InvalidIdException.class) - public void testWithEmptyStringId() { - ObjectRepository repository = db.getRepository(WithEmptyStringId.class); - WithEmptyStringId object = new WithEmptyStringId(); - object.setName(""); // empty id value - - WriteResult result = repository.insert(object); - for (NitriteId id : result) { - WithEmptyStringId instance = repository.getById(id); - assertEquals(instance, object); - } - } - - @Test(expected = InvalidIdException.class) - public void testWithNullId() { - ObjectRepository repository = db.getRepository(WithNullId.class); - WithNullId object = new WithNullId(); - - WriteResult result = repository.insert(object); - for (NitriteId id : result) { - WithNullId instance = repository.getById(id); - assertEquals(instance, object); - } - } - - @Test(expected = ValidationException.class) - public void testWithValueTypeRepository() { - ObjectRepository repository = db.getRepository(String.class); - repository.insert("test"); - } - - @Test(expected = InvalidOperationException.class) - public void testFindResultRemove() { - ObjectRepository repository = db.getRepository(Employee.class); - repository.insert(DataGenerator.generateEmployee()); - RecordStream result = repository.find(); - result.iterator().remove(); - } - - @Test(expected = InvalidOperationException.class) - public void testWithObjectId() { - ObjectRepository repository = db.getRepository(WithObjectId.class); - WithOutId id = new WithOutId(); - id.setName("test"); - id.setNumber(1); - - WithObjectId object = new WithObjectId(); - object.setWithOutId(id); - repository.insert(object); - } - - @Test(expected = NotIdentifiableException.class) - public void testUpdateNoId() { - ObjectRepository repository = db.getRepository(WithOutId.class); - WithOutId object = new WithOutId(); - object.setName("name"); - object.setNumber(1L); - repository.update(object); - } - - @Test(expected = NotIdentifiableException.class) - public void testRemoveNoId() { - ObjectRepository repository = db.getRepository(WithOutId.class); - WithOutId object = new WithOutId(); - object.setName("name"); - object.setNumber(1L); - repository.remove(object); - } - - @Test(expected = ValidationException.class) - public void testProjectionFailedInstantiate() { - ObjectRepository repository = db.getRepository(WithOutId.class); - WithOutId object = new WithOutId(); - object.setName("name"); - object.setNumber(1L); - repository.insert(object); - - RecordStream project = repository.find().project(NitriteId.class); - assertNull(project.toList()); - } - - @Test(expected = ValidationException.class) - public void testNullInsert() { - ObjectRepository repository = db.getRepository(WithOutId.class); - repository.insert(null); - } - - @Test(expected = InvalidIdException.class) - public void testGetByNullId() { - ObjectRepository repository = db.getRepository(WithPublicField.class); - WithPublicField object = new WithPublicField(); - object.name = "test"; - object.number = 2; - - repository.insert(object); - WithPublicField instance = repository.getById(null); - assertEquals(object.name, instance.name); - assertEquals(object.number, instance.number); - } - - @Test - public void testExternalNitriteId() { - ObjectRepository repository = db.getRepository(WithNitriteId.class); - WithNitriteId obj = new WithNitriteId(); - NitriteId id = NitriteId.createId("1"); - obj.setIdField(id); - obj.setName("testExternalNitriteId"); - WriteResult result = repository.update(obj, true); - - obj = new WithNitriteId(); - id = result.iterator().next(); - obj.setIdField(id); - obj.setName("testExternalNitriteId"); - result = repository.update(obj, true); - assertNotEquals(id.getIdValue(), result.iterator().next().getIdValue()); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/ObjectRepositoryTest.java b/nitrite/src/test/java/org/dizitart/no2/repository/ObjectRepositoryTest.java deleted file mode 100644 index 0e4311df9..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/ObjectRepositoryTest.java +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import com.github.javafaker.Faker; -import lombok.Data; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.Retry; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.MappableMapper; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Entity; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.data.*; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.util.Date; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.awaitility.Awaitility.await; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.module.NitriteModule.module; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class ObjectRepositoryTest { - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - NitriteMapper mapper = new MappableMapper(); - - db = Nitrite.builder() - .loadModule(module(mapper)) - .fieldSeparator(".") - .openOrCreate(); - } - - @After - public void close() { - db.close(); - db = null; - } - - @Test - public void testWithClassField() { - ObjectRepository repository = db.getRepository(WithClassField.class); - - WithClassField object = new WithClassField(); - object.setName("test"); - object.setClazz(String.class); - - repository.insert(object); - WithClassField instance = repository.getById("test"); - assertEquals(instance.getName(), object.getName()); - assertEquals(instance.getClazz(), object.getClazz()); - } - - @Test - public void testWithFinalField() { - ObjectRepository repository = db.getRepository(WithFinalField.class); - WithFinalField object = new WithFinalField(); - object.setName("test"); - - repository.insert(object); - for (WithFinalField instance : repository.find()) { - assertEquals(object.getName(), instance.getName()); - assertEquals(object.getNumber(), instance.getNumber()); - } - } - - @Test - public void testWithOutGetterSetter() { - ObjectRepository repository = db.getRepository(WithOutGetterSetter.class); - WithOutGetterSetter object = new WithOutGetterSetter(); - - repository.insert(object); - for (WithOutGetterSetter instance : repository.find()) { - assertEquals(object, instance); - } - } - - @Test - public void testWithOutId() { - ObjectRepository repository = db.getRepository(WithOutId.class); - WithOutId object = new WithOutId(); - object.setName("test"); - object.setNumber(2); - - repository.insert(object); - for (WithOutId instance : repository.find()) { - assertEquals(object.getName(), instance.getName()); - assertEquals(object.getNumber(), instance.getNumber()); - } - } - - @Test - public void testWithPublicField() { - ObjectRepository repository = db.getRepository(WithPublicField.class); - WithPublicField object = new WithPublicField(); - object.name = "test"; - object.number = 2; - - repository.insert(object); - WithPublicField instance = repository.getById("test"); - assertEquals(object.name, instance.name); - assertEquals(object.number, instance.number); - } - - @Test - public void testWithTransientField() { - ObjectRepository repository = db.getRepository(WithTransientField.class); - WithTransientField object = new WithTransientField(); - object.setNumber(2); - object.setName("test"); - - repository.insert(object); - WithTransientField instance = repository.getById(2L); - assertNotEquals(object.getName(), instance.getName()); - assertNull(instance.getName()); - assertEquals(object.getNumber(), instance.getNumber()); - } - - @Test - public void testWriteThousandRecords() { - int count = 5000; - - ObjectRepository repository = db.getRepository(StressRecord.class); - - for (int i = 0; i < count; i++) { - StressRecord record = new StressRecord(); - record.setFirstName(UUID.randomUUID().toString()); - record.setFailed(false); - record.setLastName(UUID.randomUUID().toString()); - record.setProcessed(false); - - repository.insert(record); - } - - Cursor cursor - = repository.find(where("failed").eq(false)); - for (StressRecord record : cursor) { - record.setProcessed(true); - repository.update(where("firstName").eq(record.getFirstName()), record); - } - } - - @Test - public void testWithPackagePrivateClass() { - ObjectRepository repository = db.getRepository(InternalClass.class); - InternalClass internalClass = new InternalClass(); - internalClass.setId(1); - internalClass.setName("name"); - - repository.insert(internalClass); - InternalClass instance = repository.getById((long) 1); - assertEquals(internalClass.getName(), instance.getName()); - assertEquals(internalClass.getId(), instance.getId()); - } - - @Test - public void testWithPrivateConstructor() { - ObjectRepository repository = - db.getRepository(WithPrivateConstructor.class); - - WithPrivateConstructor object = WithPrivateConstructor.create("test", 2L); - repository.insert(object); - for (WithPrivateConstructor instance : repository.find()) { - assertEquals(object, instance); - } - } - - @Test - public void testWithDateAsId() { - ObjectRepository repository = db.getRepository(WithDateId.class); - - WithDateId object1 = new WithDateId(); - object1.setId(new Date(1482773634L)); - object1.setName("first date"); - repository.insert(object1); - - WithDateId object2 = new WithDateId(); - object2.setName("second date"); - object2.setId(new Date(1482773720L)); - repository.insert(object2); - - assertEquals(repository.find(where("id").eq(new Date(1482773634L))) - .firstOrNull(), object1); - assertEquals(repository.find(where("id").eq(new Date(1482773720L))) - .firstOrNull(), object2); - } - - @Test - public void testWithIdInheritance() { - ObjectRepository repository = db.getRepository(ChildClass.class); - assertTrue(repository.hasIndex("id")); - assertTrue(repository.hasIndex("date")); - assertTrue(repository.hasIndex("text")); - - ChildClass childClass = new ChildClass(); - childClass.setName("first"); - childClass.setDate(new Date(100000L)); - childClass.setId(1L); - childClass.setText("I am first class"); - repository.insert(childClass); - - childClass = new ChildClass(); - childClass.setName("seconds"); - childClass.setDate(new Date(100001L)); - childClass.setId(2L); - childClass.setText("I am second class"); - repository.insert(childClass); - - childClass = new ChildClass(); - childClass.setName("third"); - childClass.setDate(new Date(100002L)); - childClass.setId(3L); - childClass.setText("I am third class"); - repository.insert(childClass); - - assertEquals(repository.find(where("text").text("class")).size(), 3); - assertEquals(repository.find(where("text").text("second")).size(), 0); // filtered in stop words - assertEquals(repository.find(where("date").eq(new Date(100000L))).size(), 1); - assertEquals(repository.find(where("id").eq(1L)).size(), 1); - } - - @Test - public void testAttributes() { - ObjectRepository repository = db.getRepository(WithDateId.class); - Attributes attributes = new Attributes(repository.getDocumentCollection().getName()); - repository.setAttributes(attributes); - assertEquals(repository.getAttributes(), attributes); - } - - @Test - public void testKeyedRepository() { - // an object repository of employees who are managers - ObjectRepository managerRepo = db.getRepository(Employee.class, "managers"); - - // an object repository of all employee - ObjectRepository employeeRepo = db.getRepository(Employee.class); - - // and object repository of employees who are developers - ObjectRepository developerRepo = db.getRepository(Employee.class, "developers"); - - Employee manager = new Employee(); - manager.setEmpId(1L); - manager.setAddress("abcd"); - manager.setJoinDate(new Date()); - - Employee developer = new Employee(); - developer.setEmpId(2L); - developer.setAddress("xyz"); - developer.setJoinDate(new Date()); - - managerRepo.insert(manager); - employeeRepo.insert(manager, developer); - developerRepo.insert(developer); - - assertTrue(db.hasRepository(Employee.class)); - assertTrue(db.hasRepository(Employee.class, "managers")); - assertTrue(db.hasRepository(Employee.class, "developers")); - - assertEquals(db.listRepositories().size(), 1); - assertEquals(db.listKeyedRepository().size(), 2); - - assertEquals(employeeRepo.find(where("address").eq("abcd")).size(), 1); - assertEquals(employeeRepo.find(where("address").eq("xyz")).size(), 1); - assertEquals(managerRepo.find(where("address").eq("xyz")).size(), 0); - assertEquals(managerRepo.find(where("address").eq("abcd")).size(), 1); - assertEquals(developerRepo.find(where("address").eq("xyz")).size(), 1); - assertEquals(developerRepo.find(where("address").eq("abcd")).size(), 0); - } - - @Test - public void testEntityRepository() { - ObjectRepository managerRepo = db.getRepository(EmployeeEntity.class, "managers"); - ObjectRepository employeeRepo = db.getRepository(EmployeeEntity.class); - ObjectRepository developerRepo = db.getRepository(EmployeeEntity.class, "developers"); - - managerRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); - employeeRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); - developerRepo.insert(new EmployeeEntity(), new EmployeeEntity(), new EmployeeEntity()); - - boolean errored = false; - try { - NitriteCollection collection = db.getCollection("entity.employee"); - } catch (ValidationException e) { - errored = true; - } - assertTrue(errored); - - assertTrue(db.listRepositories().contains("entity.employee")); - assertEquals(db.listKeyedRepository().size(), 2); - assertEquals(db.listCollectionNames().size(), 0); - - assertTrue(managerRepo.hasIndex("firstName")); - assertTrue(managerRepo.hasIndex("lastName")); - assertTrue(employeeRepo.hasIndex("lastName")); - assertTrue(employeeRepo.hasIndex("lastName")); - - managerRepo.drop(); - assertEquals(db.listKeyedRepository().size(), 1); - } - - @Test - public void testIssue217() { - ObjectRepository employeeRepo = db.getRepository(EmployeeEntity.class); - AtomicInteger counter = new AtomicInteger(0); - employeeRepo.subscribe(eventInfo -> counter.incrementAndGet()); - - ObjectRepository employeeRepo2 = db.getRepository(EmployeeEntity.class); - employeeRepo2.insert(new EmployeeEntity()); - await().atMost(5, TimeUnit.SECONDS).until(() -> counter.get() == 1); - } - - @Data - @Entity(value = "entity.employee", indices = { - @Index(value = "firstName", type = IndexType.NonUnique), - @Index(value = "lastName", type = IndexType.NonUnique), - }) - private static class EmployeeEntity implements Mappable { - private static final Faker faker = new Faker(); - - @Id - private Long id; - private String firstName; - private String lastName; - - public EmployeeEntity() { - id = faker.number().randomNumber(); - firstName = faker.name().firstName(); - lastName = faker.name().lastName(); - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("id", id) - .put("firstName", firstName) - .put("lastName", lastName); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Long.class); - firstName = document.get("firstName", String.class); - lastName = document.get("lastName", String.class); - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/ProjectionTest.java b/nitrite/src/test/java/org/dizitart/no2/repository/ProjectionTest.java deleted file mode 100644 index 30c7d27e9..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/ProjectionTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.repository.data.SubEmployee; -import org.junit.Test; - -import java.util.Iterator; - -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -public class ProjectionTest extends BaseObjectRepositoryTest { - - @Test - public void testHasMore() { - RecordStream iterable = employeeRepository.find().skipLimit(0, 5) - .project(SubEmployee.class); - assertFalse(iterable.isEmpty()); - } - - @Test - public void testSize() { - RecordStream iterable = employeeRepository.find().skipLimit(0, 5) - .project(SubEmployee.class); - assertEquals(iterable.size(), 5); - } - - @Test - public void testToString() { - RecordStream iterable = employeeRepository.find().skipLimit(0, 5) - .project(SubEmployee.class); - assertNotNull(iterable.toString()); - } - - @Test(expected = InvalidOperationException.class) - public void testRemove() { - RecordStream iterable = employeeRepository.find().skipLimit(0, 5) - .project(SubEmployee.class); - Iterator iterator = iterable.iterator(); - if (iterator.hasNext()) { - iterator.next(); - iterator.remove(); - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/ReflectorTest.java b/nitrite/src/test/java/org/dizitart/no2/repository/ReflectorTest.java new file mode 100644 index 000000000..4a19153bb --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/repository/ReflectorTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.repository; + +import org.dizitart.no2.exceptions.ValidationException; +import org.junit.Test; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; + +import static org.junit.Assert.*; + +public class ReflectorTest { + @Test + public void testFindInheritedAnnotations() { + Reflector reflector = new Reflector(); + Class annotation = Annotation.class; + assertTrue(reflector.findInheritedAnnotations(annotation, Object.class).isEmpty()); + } + + @Test + public void testFindInheritedAnnotations3() { + Reflector reflector = new Reflector(); + Class annotation = Annotation.class; + assertTrue(reflector.findInheritedAnnotations(annotation, Field.class).isEmpty()); + } + + @Test + public void testGetEmbeddedField() { + Reflector reflector = new Reflector(); + assertThrows(ValidationException.class, () -> reflector.getEmbeddedField(Object.class, "Embedded Field")); + } + + @Test + public void testGetEmbeddedField2() { + Reflector reflector = new Reflector(); + assertThrows(ValidationException.class, () -> reflector.getEmbeddedField(Object.class, "\\{0}")); + } + + @Test + public void testGetEmbeddedField3() { + Reflector reflector = new Reflector(); + assertThrows(ValidationException.class, () -> reflector.getEmbeddedField(Object.class, "")); + } + + @Test + public void testGetEmbeddedField4() { + Reflector reflector = new Reflector(); + assertThrows(ValidationException.class, () -> reflector.getEmbeddedField(Object.class, "java.lang.Object")); + } + + @Test + public void testGetFieldsUpto() { + Reflector reflector = new Reflector(); + Class startClass = Object.class; + assertTrue(reflector.getFieldsUpto(startClass, Object.class).isEmpty()); + } + + @Test + public void testGetFieldsUpto2() { + Reflector reflector = new Reflector(); + Class startClass = Field.class; + assertEquals(Short.SIZE, reflector.getFieldsUpto(startClass, Object.class).size()); + } + + @Test + public void testGetField() { + Reflector reflector = new Reflector(); + assertThrows(ValidationException.class, () -> reflector.getField(Object.class, "Name")); + } + + + @Test + public void testGetField3() { + Reflector reflector = new Reflector(); + assertThrows(ValidationException.class, + () -> reflector.getField(Object.class, "startClass cannot be null")); + } + + @Test + public void testGetField4() { + Reflector reflector = new Reflector(); + assertThrows(ValidationException.class, () -> reflector.getField(Object.class, "no such field '")); + } + + @Test + public void testGetField5() { + Reflector reflector = new Reflector(); + assertThrows(ValidationException.class, () -> reflector.getField(Object.class, "java.lang.Object")); + } + + @Test + public void testGetAllFields() { + Reflector reflector = new Reflector(); + assertTrue(reflector.getAllFields(Object.class).isEmpty()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/RepositoryFactoryTest.java b/nitrite/src/test/java/org/dizitart/no2/repository/RepositoryFactoryTest.java index e012507f7..27eeed486 100644 --- a/nitrite/src/test/java/org/dizitart/no2/repository/RepositoryFactoryTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/repository/RepositoryFactoryTest.java @@ -1,219 +1,55 @@ /* - * Copyright (c) 2017-2020. Nitrite author or authors. + * Copyright (c) 2017-2021 Nitrite author or authors. * * Licensed 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 + * 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.dizitart.no2.repository; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.Retry; -import org.dizitart.no2.TestUtil; -import org.dizitart.no2.collection.*; -import org.dizitart.no2.collection.events.CollectionEventListener; -import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.common.WriteResult; +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.collection.CollectionFactory; import org.dizitart.no2.common.concurrent.LockService; import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexEntry; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.store.NitriteStore; -import org.junit.After; -import org.junit.Rule; import org.junit.Test; -import java.util.Collection; - -import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; -/** - * @author Anindya Chatterjee - */ public class RepositoryFactoryTest { - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); @Test - public void testRepositoryFactory() { - RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); - assertNotNull(factory); - } - - @Test(expected = ValidationException.class) - public void testNullType() { - RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); - db = TestUtil.createDb(); - factory.getRepository(db.getConfig(), null, "dummy"); + public void testGetRepository() { + RepositoryFactory repositoryFactory = new RepositoryFactory(new CollectionFactory(new LockService())); + assertThrows(ValidationException.class, () -> repositoryFactory.getRepository(null, Object.class)); } @Test - public void testNullCollection() { - RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); - db = TestUtil.createDb(); - factory.getRepository(db.getConfig(), DummyCollection.class, null); + public void testGetRepository2() { + RepositoryFactory repositoryFactory = new RepositoryFactory(new CollectionFactory(new LockService())); + assertThrows(ValidationException.class, () -> repositoryFactory.getRepository(new NitriteConfig(), null)); } - @Test(expected = ValidationException.class) - public void testNullContext() { - RepositoryFactory factory = new RepositoryFactory(new CollectionFactory(new LockService())); - factory.getRepository(null, DummyCollection.class, "dummy"); - } - - @After - public void cleanUp() { - if (db != null && !db.isClosed()) { - db.close(); - } + @Test + public void testGetRepository3() { + RepositoryFactory repositoryFactory = new RepositoryFactory(new CollectionFactory(new LockService())); + assertThrows(ValidationException.class, () -> repositoryFactory.getRepository(null, Object.class, "Key")); } - private static class DummyCollection implements NitriteCollection { - - @Override - public WriteResult update(Filter filter, Document update, UpdateOptions updateOptions) { - return null; - } - - @Override - public WriteResult remove(Filter filter, boolean justOne) { - return null; - } - - @Override - public DocumentCursor find() { - return null; - } - - @Override - public DocumentCursor find(Filter filter) { - return null; - } - - @Override - public Document getById(NitriteId nitriteId) { - return null; - } - - @Override - public String getName() { - return null; - } - - @Override - public void createIndex(String field, IndexOptions indexOptions) { - - } - - @Override - public void rebuildIndex(String field, boolean isAsync) { - - } - - @Override - public Collection listIndices() { - return null; - } - - @Override - public boolean hasIndex(String field) { - return false; - } - - @Override - public boolean isIndexing(String field) { - return false; - } - - @Override - public void dropIndex(String field) { - - } - - @Override - public void dropAllIndices() { - - } - - @Override - public WriteResult insert(Document[] elements) { - return null; - } - - @Override - public WriteResult update(Document element, boolean insertIfAbsent) { - return null; - } - - @Override - public WriteResult remove(Document element) { - return null; - } - - @Override - public void clear() { - - } - - @Override - public void drop() { - - } - - @Override - public boolean isDropped() { - return false; - } - - @Override - public boolean isOpen() { - return false; - } - - @Override - public void close() { - - } - - @Override - public long size() { - return 0; - } - - @Override - public NitriteStore getStore() { - return null; - } - - @Override - public void subscribe(CollectionEventListener listener) { - - } - - @Override - public void unsubscribe(CollectionEventListener listener) { - - } - - @Override - public Attributes getAttributes() { - return null; - } - - @Override - public void setAttributes(Attributes attributes) { - - } + @Test + public void testGetRepository4() { + RepositoryFactory repositoryFactory = new RepositoryFactory(new CollectionFactory(new LockService())); + assertThrows(ValidationException.class, + () -> repositoryFactory.getRepository(new NitriteConfig(), null, "Key")); } } + diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/RepositoryJoinTest.java b/nitrite/src/test/java/org/dizitart/no2/repository/RepositoryJoinTest.java deleted file mode 100644 index e76bd7d24..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/RepositoryJoinTest.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import lombok.Data; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.Retry; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.Lookup; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.exceptions.InvalidOperationException; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.io.IOException; -import java.util.*; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -@RunWith(value = Parameterized.class) -public class RepositoryJoinTest { - @Parameterized.Parameter - public boolean isProtected = false; - - protected Nitrite db; - private ObjectRepository personRepository; - private ObjectRepository
    addressRepository; - - @Rule - public Retry retry = new Retry(3); - - @Parameterized.Parameters(name = "Protected = {0}") - public static Collection data() { - return Arrays.asList(new Object[][]{ - {false}, - {true}, - }); - } - - @Before - public void setUp() { - openDb(); - - personRepository = db.getRepository(Person.class); - addressRepository = db.getRepository(Address.class); - - for (int i = 0; i < 10; i++) { - Person person = new Person(); - person.setId(Integer.toString(i)); - person.setName("Person " + i); - personRepository.insert(person); - - Address address = new Address(); - address.setPersonId(Integer.toString(i)); - address.setStreet("Street address " + i); - addressRepository.insert(address); - - if (i == 5) { - Address address2 = new Address(); - address2.setPersonId(Integer.toString(i)); - address2.setStreet("Street address 2nd " + i); - addressRepository.insert(address2); - } - } - } - - private void openDb() { - NitriteBuilder nitriteBuilder = Nitrite.builder() - .fieldSeparator("."); - - if (isProtected) { - db = nitriteBuilder.openOrCreate("test-user1", "test-password1"); - } else { - db = nitriteBuilder.openOrCreate(); - } - } - - @After - public void clear() throws IOException { - if (personRepository != null && !personRepository.isDropped()) { - personRepository.remove(ALL); - } - - if (addressRepository != null && !addressRepository.isDropped()) { - addressRepository.remove(ALL); - } - - if (db != null) { - db.commit(); - db.close(); - } - } - - @Test - public void testJoin() { - Lookup lookup = new Lookup(); - lookup.setLocalField("id"); - lookup.setForeignField("personId"); - lookup.setTargetField("addresses"); - - RecordStream result - = personRepository.find().join(addressRepository.find(), lookup, - PersonDetails.class); - assertEquals(result.size(), 10); - - for (PersonDetails personDetails : result) { - Address[] addresses = personDetails.addresses.toArray(new Address[0]); - if (personDetails.id.equals("5")) { - assertEquals(addresses.length, 2); - } else { - assertEquals(addresses.length, 1); - assertEquals(addresses[0].personId, personDetails.getId()); - } - } - - result = personRepository.find().skipLimit(0, 5).join(addressRepository.find(), lookup, - PersonDetails.class); - - assertEquals(result.size(), 5); - assertFalse(result.isEmpty()); - assertNotNull(result.toString()); - } - - @Test(expected = InvalidOperationException.class) - public void testRemove() { - Lookup lookup = new Lookup(); - lookup.setLocalField("id"); - lookup.setForeignField("personId"); - lookup.setTargetField("addresses"); - - RecordStream result - = personRepository.find().join(addressRepository.find(), lookup, - PersonDetails.class); - assertEquals(result.size(), 10); - - Iterator iterator = result.iterator(); - if (iterator.hasNext()) { - iterator.next(); - iterator.remove(); - } - } - - @Data - public static class Person implements Mappable { - @Id - private NitriteId nitriteId; - private String id; - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("nitriteId", nitriteId) - .put("id", id) - .put("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - nitriteId = document.get("nitriteId", NitriteId.class); - id = document.get("id", String.class); - name = document.get("name", String.class); - } - } - - @Data - public static class Address implements Mappable { - @Id - private NitriteId nitriteId; - private String personId; - private String street; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("nitriteId", nitriteId) - .put("personId", personId) - .put("street", street); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - nitriteId = document.get("nitriteId", NitriteId.class); - personId = document.get("personId", String.class); - street = document.get("street", String.class); - } - } - - @Data - public static class PersonDetails implements Mappable { - @Id - private NitriteId nitriteId; - private String id; - private String name; - private List
    addresses; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("nitriteId", nitriteId) - .put("personId", id) - .put("street", name) - .put("addresses", addresses); - } - - @Override - @SuppressWarnings("unchecked") - public void read(NitriteMapper mapper, Document document) { - nitriteId = document.get("nitriteId", NitriteId.class); - id = document.get("id", String.class); - name = document.get("name", String.class); - Set documents = document.get("addresses", Set.class); - this.addresses = new ArrayList<>(); - for (Document doc : documents) { - Address address = new Address(); - address.read(mapper, doc); - addresses.add(address); - } - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/RepositoryModificationTest.java b/nitrite/src/test/java/org/dizitart/no2/repository/RepositoryModificationTest.java deleted file mode 100644 index 7c0813651..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/RepositoryModificationTest.java +++ /dev/null @@ -1,631 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.common.WriteResult; -import org.dizitart.no2.exceptions.InvalidIdException; -import org.dizitart.no2.exceptions.UniqueConstraintException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexEntry; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.repository.data.*; -import org.junit.Test; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Collection; -import java.util.Date; -import java.util.Locale; - -import static org.awaitility.Awaitility.await; -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.*; - - -/** - * @author Anindya Chatterjee. - */ -public class RepositoryModificationTest extends BaseObjectRepositoryTest { - - @Test - public void testCreateIndex() { - assertTrue(companyRepository.hasIndex("companyName")); - assertFalse(companyRepository.hasIndex("dateCreated")); - - companyRepository.createIndex("dateCreated", IndexOptions.indexOptions(IndexType.NonUnique)); - assertTrue(companyRepository.hasIndex("dateCreated")); - assertFalse(companyRepository.isIndexing("dateCreated")); - } - - @Test - public void testRebuildIndex() { - companyRepository.createIndex("dateCreated", IndexOptions.indexOptions(IndexType.NonUnique)); - assertFalse(companyRepository.isIndexing("dateCreated")); - - companyRepository.rebuildIndex("dateCreated", true); - assertTrue(companyRepository.isIndexing("dateCreated")); - - await().until(() -> !companyRepository.isIndexing("dateCreated")); - } - - @Test - public void testListIndexes() { - Collection indices = companyRepository.listIndices(); - assertEquals(indices.size(), 2); - - companyRepository.createIndex("dateCreated", IndexOptions.indexOptions(IndexType.NonUnique)); - indices = companyRepository.listIndices(); - assertEquals(indices.size(), 3); - } - - @Test - public void testDropIndex() { - testListIndexes(); - companyRepository.dropIndex("dateCreated"); - Collection indices = companyRepository.listIndices(); - assertEquals(indices.size(), 2); - } - - @Test - public void testDropAllIndex() { - testListIndexes(); - companyRepository.dropAllIndices(); - Collection indices = companyRepository.listIndices(); - assertEquals(indices.size(), 0); - } - - @Test - public void testCompanyRecord() { - Cursor cursor = companyRepository.find(); - assertEquals(cursor.size(), 10); - assertFalse(cursor.isEmpty()); - } - - @Test - public void testInsert() { - Company company = DataGenerator.generateCompanyRecord(); - Cursor cursor = companyRepository.find(); - assertEquals(cursor.size(), 10); - - companyRepository.insert(company); - cursor = companyRepository.find(); - assertEquals(cursor.size(), 11); - - Company company1 = DataGenerator.generateCompanyRecord(); - Company company2 = DataGenerator.generateCompanyRecord(); - companyRepository.insert(new Company[]{company1, company2}); - cursor = companyRepository.find(); - assertEquals(cursor.size(), 13); - } - - @Test - public void testUpdateWithFilter() { - employeeRepository.remove(Filter.ALL); - - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("abcd road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(new Date()); - Note empNote = new Note(); - empNote.setNoteId(23L); - empNote.setText("sample text note"); - employee.setEmployeeNote(empNote); - - employeeRepository.insert(employee); - Cursor result = employeeRepository.find(); - assertEquals(result.size(), 1); - for (Employee e : result) { - assertEquals(e.getAddress(), "abcd road"); - } - - Employee updated = new Employee(employee); - updated.setAddress("xyz road"); - WriteResult writeResult = employeeRepository.update(where("empId").eq(12L), updated); - assertEquals(writeResult.getAffectedCount(), 1); - result = employeeRepository.find(); - assertEquals(result.size(), 1); - for (Employee e : result) { - assertEquals(e.getAddress(), "xyz road"); - } - } - - @Test - public void testUpdateWithJustOnceFalse() throws ParseException { - Date joiningDate = new Date(); - prepareUpdateWithOptions(joiningDate); - - SimpleDateFormat simpleDateFormat - = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH); - Date newJoiningDate = simpleDateFormat.parse("2012-07-01T16:02:48.440Z"); - - Document updated1 = createDocument(); - updated1.put("joinDate", newJoiningDate); - - WriteResult writeResult - = employeeRepository.update(where("empId").eq(12L), updated1, false); - assertEquals(writeResult.getAffectedCount(), 1); - - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 1); - result = employeeRepository.find(where("joinDate").eq(newJoiningDate)); - assertEquals(result.size(), 1); - - employeeRepository.remove(Filter.ALL); - prepareUpdateWithOptions(joiningDate); - result = employeeRepository.find(); - assertEquals(result.size(), 2); - - Document update = createDocument(); - update.put("joinDate", newJoiningDate); - - writeResult = employeeRepository.update(where("joinDate").eq(joiningDate), update, false); - assertEquals(writeResult.getAffectedCount(), 2); - - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - - result = employeeRepository.find(where("joinDate").eq(newJoiningDate)); - assertEquals(result.size(), 2); - } - - @Test - public void testUpsertTrue() { - Date joiningDate = new Date(); - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("some road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(joiningDate); - Note empNote1 = new Note(); - empNote1.setNoteId(23L); - empNote1.setText("sample text note"); - employee.setEmployeeNote(empNote1); - - WriteResult writeResult - = employeeRepository.update(where("empId").eq(12), employee, true); - assertEquals(writeResult.getAffectedCount(), 1); - - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 1); - } - - @Test - public void testUpsertFalse() { - Date joiningDate = new Date(); - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("some road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(joiningDate); - Note empNote1 = new Note(); - empNote1.setNoteId(23L); - empNote1.setText("sample text note"); - employee.setEmployeeNote(empNote1); - - WriteResult writeResult - = employeeRepository.update(where("empId").eq(12), employee, false); - assertEquals(writeResult.getAffectedCount(), 0); - - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - } - - @Test - public void testDeleteFilterAndWithOutOption() { - Date joiningDate = new Date(); - prepareUpdateWithOptions(joiningDate); - - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 2); - - WriteResult writeResult = employeeRepository.remove(where("joinDate").eq(joiningDate)); - assertEquals(writeResult.getAffectedCount(), 2); - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 0); - } - - @Test - public void testDeleteFilterAndWithOption() { - Date joiningDate = new Date(); - prepareUpdateWithOptions(joiningDate); - - Cursor result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 2); - - WriteResult writeResult = employeeRepository.remove(where("joinDate").eq(joiningDate), true); - assertEquals(writeResult.getAffectedCount(), 1); - result = employeeRepository.find(where("joinDate").eq(joiningDate)); - assertEquals(result.size(), 1); - } - - @Test - public void testEmployeeRecord() { - Iterable totalResult = employeeRepository.find(); - int occurrence = 0; - for (Employee employee : totalResult) { - if (employee.getEmployeeNote().getText().toLowerCase().contains("class aptent")) { - occurrence++; - } - } - - Cursor cursor = employeeRepository.find(where("employeeNote.text").text("Class aptent")); - assertEquals(cursor.size(), occurrence); - } - - @Test - public void testUpdateWithOptions() { - Employee employee = employeeRepository.find().firstOrNull(); - - Document update = createDocument(); - update.put("address", "new address"); - - WriteResult writeResult - = employeeRepository.update(where("empId").eq(employee.getEmpId()), update, false); - assertEquals(writeResult.getAffectedCount(), 1); - - Employee byId = employeeRepository.getById(employee.getEmpId()); - assertEquals(byId.getAddress(), "new address"); - assertEquals(byId.getEmpId(), employee.getEmpId()); - - update.put("address", "another address"); - employeeRepository.update(where("empId").eq(employee.getEmpId()), update); - - byId = employeeRepository.getById(employee.getEmpId()); - assertEquals(byId.getAddress(), "another address"); - assertEquals(byId.getEmpId(), employee.getEmpId()); - } - - @Test(expected = InvalidIdException.class) - public void testMultiUpdateWithObject() { - employeeRepository.remove(Filter.ALL); - - Date now = new Date(); - Employee employee1 = new Employee(); - employee1.setEmpId(1L); - employee1.setAddress("abcd"); - employee1.setJoinDate(now); - - Employee employee2 = new Employee(); - employee2.setEmpId(2L); - employee2.setAddress("xyz"); - employee2.setJoinDate(now); - employeeRepository.insert(employee1, employee2); - - Employee update = new Employee(); - update.setAddress("new address"); - - WriteResult writeResult - = employeeRepository.update(where("joinDate").eq(now), update, false); - assertEquals(writeResult.getAffectedCount(), 0); - } - - @Test - public void testUpdateNull() { - Employee employee = employeeRepository.find().firstOrNull(); - Employee newEmployee = new Employee(employee); - newEmployee.setJoinDate(null); - - Employee result = employeeRepository.find(where("empId").eq(employee.getEmpId())).firstOrNull(); - assertNotNull(result.getJoinDate()); - - WriteResult writeResult = employeeRepository.update(newEmployee, false); - assertEquals(writeResult.getAffectedCount(), 1); - - result = employeeRepository.find(where("empId").eq(employee.getEmpId())).firstOrNull(); - assertNull(result.getJoinDate()); - - // update with object filter and item and set id different - } - - @Test - public void testUpdateWithChangedId() { - Employee employee = employeeRepository.find().firstOrNull(); - Long oldId = employee.getEmpId(); - long count = employeeRepository.size(); - - Employee newEmployee = new Employee(employee); - newEmployee.setEmpId(50L); - - Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); - assertNotNull(result.getJoinDate()); - - WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); - assertEquals(writeResult.getAffectedCount(), 1); - - assertEquals(count, employeeRepository.size()); - Cursor cursor = employeeRepository.find(where("empId").eq(oldId)); - assertEquals(cursor.size(), 0); - } - - @Test(expected = InvalidIdException.class) - public void testUpdateWithNullId() { - Employee employee = employeeRepository.find().firstOrNull(); - Long oldId = employee.getEmpId(); - - Employee newEmployee = new Employee(employee); - newEmployee.setEmpId(null); - - Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); - assertNotNull(result.getJoinDate()); - - WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); - assertEquals(writeResult.getAffectedCount(), 1); - } - - @Test(expected = UniqueConstraintException.class) - public void testUpdateWithDuplicateId() { - Employee employee = employeeRepository.find().firstOrNull(); - Long oldId = employee.getEmpId(); - long count = employeeRepository.size(); - - Employee newEmployee = new Employee(employee); - newEmployee.setEmpId(5L); - - Employee result = employeeRepository.find(where("empId").eq(oldId)).firstOrNull(); - assertNotNull(result.getJoinDate()); - - WriteResult writeResult = employeeRepository.update(where("empId").eq(oldId), newEmployee, false); - assertEquals(writeResult.getAffectedCount(), 1); - - assertEquals(count, employeeRepository.size()); - Cursor cursor = employeeRepository.find(where("empId").eq(oldId)); - assertEquals(cursor.size(), 0); - } - - @Test - public void testUpdateWithObject() { - Employee employee = employeeRepository.find().firstOrNull(); - Employee newEmployee = new Employee(employee); - - Long id = employee.getEmpId(); - String address = employee.getAddress(); - newEmployee.setAddress("new address"); - - WriteResult writeResult = employeeRepository.update(newEmployee); - assertEquals(writeResult.getAffectedCount(), 1); - - Employee emp = employeeRepository.find(where("empId").eq(id)).firstOrNull(); - assertNotEquals(address, emp.getAddress()); - assertEquals(employee.getEmpId(), emp.getEmpId()); - assertEquals(employee.getJoinDate(), emp.getJoinDate()); - assertArrayEquals(employee.getBlob(), emp.getBlob()); - } - - @Test - public void testUpsertWithObject() { - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("some road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(new Date()); - Note empNote = new Note(); - empNote.setNoteId(23L); - empNote.setText("sample text note"); - employee.setEmployeeNote(empNote); - - WriteResult writeResult = employeeRepository.update(employee, false); - assertEquals(writeResult.getAffectedCount(), 0); - writeResult = employeeRepository.update(employee, true); - assertEquals(writeResult.getAffectedCount(), 1); - - Employee emp = employeeRepository.find(where("empId").eq(12L)).firstOrNull(); - assertEquals(emp, employee); - } - - @Test - public void testRemoveObject() { - Employee employee = new Employee(); - employee.setCompany(null); - employee.setAddress("some road"); - employee.setBlob(new byte[]{1, 2, 125}); - employee.setEmpId(12L); - employee.setJoinDate(new Date()); - Note empNote = new Note(); - empNote.setNoteId(23L); - empNote.setText("sample text note"); - employee.setEmployeeNote(empNote); - - long size = employeeRepository.size(); - - employeeRepository.insert(employee); - assertEquals(employeeRepository.size(), size + 1); - - employeeRepository.remove(employee); - assertEquals(employeeRepository.size(), size); - - Employee emp = employeeRepository.find(where("empId").eq(12L)).firstOrNull(); - assertNull(emp); - } - - private void prepareUpdateWithOptions(Date joiningDate) { - employeeRepository.remove(Filter.ALL); - - Employee employee1 = new Employee(); - employee1.setCompany(null); - employee1.setAddress("some road"); - employee1.setBlob(new byte[]{1, 2, 125}); - employee1.setEmpId(12L); - employee1.setJoinDate(joiningDate); - Note empNote1 = new Note(); - empNote1.setNoteId(23L); - empNote1.setText("sample text note"); - employee1.setEmployeeNote(empNote1); - - Employee employee2 = new Employee(); - employee2.setCompany(null); - employee2.setAddress("other road"); - employee2.setBlob(new byte[]{10, 12, 25}); - employee2.setEmpId(2L); - employee2.setJoinDate(joiningDate); - Note empNote2 = new Note(); - empNote2.setNoteId(2L); - empNote2.setText("some random note"); - employee2.setEmployeeNote(empNote2); - - employeeRepository.insert(employee1, employee2); - Cursor result = employeeRepository.find(); - assertEquals(result.size(), 2); - for (Employee e : result.project(Employee.class)) { - assertEquals(e.getJoinDate(), joiningDate); - } - } - - @Test - public void testUpdateWithDoc() { - Note note = new Note(); - note.setNoteId(10L); - note.setText("some note text"); - - Document document = createDocument("address", "some address") - .put("employeeNote", note); - - WriteResult result = employeeRepository.update(Filter.ALL, document); - assertEquals(result.getAffectedCount(), 10); - } - - @Test - public void testDeleteIteratorNPE() { - ObjectRepository notes = db.getRepository(Note.class); - Note one = new Note(); - one.setText("Jane"); - one.setNoteId(1L); - Note two = new Note(); - two.setText("Jill"); - two.setNoteId(2L); - - notes.insert(one, two); - - WriteResult writeResult = notes.remove(where("text").eq("Pete")); - for (NitriteId id : writeResult) { - assertNotNull(id); - } - } - - @Test - public void testDelete() { - ObjectRepository repo = db.getRepository(WithNitriteId.class); - WithNitriteId one = new WithNitriteId(); - one.setName("Jane"); - repo.insert(one); - - WithNitriteId note = repo.find().firstOrNull(); - repo.remove(note); - - assertNull(repo.getById(one.idField)); - } - - /* - * Upsert Use Cases - * - * 1. Object does not exists - * a. if upsert true, it will insert - * b. if upsert false, nothing happens - * 2. Object exists - * a. if upsert true, it will update, old id remains same - * b. if upsert false, it will update, old id remains same - * - * */ - - @Test - public void testUpdateObjectNotExistsUpsertTrue() { - ObjectRepository repo = db.getRepository(InternalClass.class); - InternalClass a = new InternalClass(); - a.setId(1); - a.setName("first"); - repo.insert(a); - - a = new InternalClass(); - a.setId(2); - a.setName("second"); - - // it will insert as new object - repo.update(a, true); - assertEquals(repo.size(), 2); - } - - @Test - public void testUpdateObjectNotExistsUpsertFalse() { - ObjectRepository repo = db.getRepository(InternalClass.class); - InternalClass a = new InternalClass(); - a.setId(1); - a.setName("first"); - repo.insert(a); - - a = new InternalClass(); - a.setId(2); - a.setName("second"); - - // no changes will happen to repository - repo.update(a, false); - assertEquals(repo.size(), 1); - assertEquals(repo.find().firstOrNull().getId(), 1); - assertEquals(repo.find().firstOrNull().getName(), "first"); - } - - @Test - public void testUpdateObjectExistsUpsertTrue() { - ObjectRepository repo = db.getRepository(InternalClass.class); - InternalClass a = new InternalClass(); - a.setId(1); - a.setName("first"); - repo.insert(a); - - a = new InternalClass(); - a.setId(1); - a.setName("second"); - - // update existing object, keep id same - repo.update(a, true); - assertEquals(repo.size(), 1); - assertEquals(repo.find().firstOrNull().getId(), 1); - assertEquals(repo.find().firstOrNull().getName(), "second"); - } - - @Test - public void testUpdateObjectExistsUpsertFalse() { - ObjectRepository repo = db.getRepository(InternalClass.class); - InternalClass a = new InternalClass(); - a.setId(1); - a.setName("first"); - repo.insert(a); - - a = new InternalClass(); - a.setId(1); - a.setName("second"); - - // update existing object, keep id same - repo.update(a, false); - assertEquals(repo.size(), 1); - assertEquals(repo.find().firstOrNull().getId(), 1); - assertEquals(repo.find().firstOrNull().getName(), "second"); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/RepositoryOperationsTest.java b/nitrite/src/test/java/org/dizitart/no2/repository/RepositoryOperationsTest.java index 52b6a8c91..df3580ea8 100644 --- a/nitrite/src/test/java/org/dizitart/no2/repository/RepositoryOperationsTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/repository/RepositoryOperationsTest.java @@ -1,401 +1,102 @@ /* - * Copyright (c) 2017-2020. Nitrite author or authors. + * Copyright (c) 2017-2021 Nitrite author or authors. * * Licensed 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 + * 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.dizitart.no2.repository; -import lombok.Getter; -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.Retry; -import org.dizitart.no2.TestUtil; +import org.dizitart.no2.NitriteBuilderTest; import org.dizitart.no2.collection.Document; -import org.dizitart.no2.common.util.ObjectUtilsTest; -import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.collection.FindOptions; +import org.dizitart.no2.collection.NitriteCollection; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.common.RecordStream; +import org.dizitart.no2.common.processors.ProcessorChain; +import org.dizitart.no2.common.streams.DocumentStream; +import org.dizitart.no2.common.tuples.Pair; import org.dizitart.no2.exceptions.NotIdentifiableException; import org.dizitart.no2.exceptions.ValidationException; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.InheritIndices; -import org.dizitart.no2.repository.data.Employee; -import org.junit.Before; -import org.junit.Rule; +import org.dizitart.no2.filters.Filter; import org.junit.Test; -import java.math.BigDecimal; -import java.util.Iterator; -import java.util.Set; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; -/** - * @author Anindya Chatterjee - */ public class RepositoryOperationsTest { - private RepositoryOperations operations; - private Nitrite db; - - @Rule - public Retry retry = new Retry(3); - - @Before - public void setUp() { - db = TestUtil.createDb(); - } - @Test - public void testIndexes() { - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(TestObjectWithIndex.class); - operations = new RepositoryOperations(TestObjectWithIndex.class, nitriteMapper, repository.getDocumentCollection()); - Set indexes = operations.extractIndices(TestObjectWithIndex.class); - assertEquals(indexes.size(), 2); - } - - @Test(expected = IndexingException.class) - public void testInvalidIndexNonComparable() { - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(ObjectWithNonComparableIndex.class); - operations = new RepositoryOperations(TestObjectWithIndex.class, nitriteMapper, repository.getDocumentCollection()); - Set indexes = operations.extractIndices(ObjectWithNonComparableIndex.class); - assertEquals(indexes.size(), 2); - } - - @Test(expected = IndexingException.class) - public void testInvalidIndexComparableAndIterable() { - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(ObjectWithIterableIndex.class); - operations = new RepositoryOperations(ObjectWithIterableIndex.class, nitriteMapper, repository.getDocumentCollection()); - operations.extractIndices(ObjectWithIterableIndex.class); - } - - @Test(expected = ValidationException.class) - public void testGetFieldsUpToNullStartClass() { - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(Employee.class); - operations = new RepositoryOperations(Employee.class, nitriteMapper, repository.getDocumentCollection()); - assertEquals(operations.getFieldsUpto(null, null).size(), 0); - } - - @Test(expected = ValidationException.class) - public void testGetFieldNoSuchField() { - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(ClassWithAnnotatedFields.class); - operations = new RepositoryOperations(ClassWithAnnotatedFields.class, nitriteMapper, repository.getDocumentCollection()); - operations.getField(getClass(), "test"); + public void testConstructor() { + Class type = Object.class; + assertThrows(ValidationException.class, + () -> new RepositoryOperations(type, new NitriteBuilderTest.CustomNitriteMapper(), null)); } @Test - public void testGetFieldsUpTo() { - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(Employee.class); - operations = new RepositoryOperations(TestObjectWithIndex.class, nitriteMapper, repository.getDocumentCollection()); - - assertEquals(operations.getFieldsUpto(A.class, B.class).size(), 3); - assertEquals(operations.getFieldsUpto(A.class, Object.class).size(), 5); - assertEquals(operations.getFieldsUpto(A.class, null).size(), 5); - - assertEquals(operations.getFieldsUpto(ClassWithAnnotatedFields.class, - Object.class).size(), 5); - assertEquals(operations.getFieldsUpto(ClassWithAnnotatedFields.class, - null).size(), 5); - assertEquals(operations.getFieldsUpto(ClassWithAnnotatedFields.class, - ClassWithNoAnnotatedFields.class).size(), 3); - } - - @Test(expected = NotIdentifiableException.class) - public void testCreateUniqueFilterInvalidId() { - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(B.class); - operations = new RepositoryOperations(B.class, nitriteMapper, repository.getDocumentCollection()); - - B b = new B(); - operations.createUniqueFilter(b); - } - - @Test(expected = NotIdentifiableException.class) - public void testGetIdFieldMultipleId() { - class Test implements Mappable { - @Id - private String id1; - - @Id - private Long id2; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("id1", id1) - .put("id2", id2); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id1 = document.get("id1", String.class); - id2 = document.get("id2", Long.class); - } - } - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(Test.class); - operations = new RepositoryOperations(Test.class, nitriteMapper, repository.getDocumentCollection()); - - operations.getIdField(Test.class); - } - - @Test(expected = ValidationException.class) - public void testInvalidEmbeddedKey() { - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(ClassWithAnnotatedFields.class); - operations = new RepositoryOperations(ClassWithAnnotatedFields.class, nitriteMapper, repository.getDocumentCollection()); - operations.getField(ClassWithAnnotatedFields.class, ".."); - } - - @Test(expected = ValidationException.class) - public void testInvalidGetField() { - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(ClassWithAnnotatedFields.class); - operations = new RepositoryOperations(ClassWithAnnotatedFields.class, nitriteMapper, repository.getDocumentCollection()); - operations.getField(ClassWithAnnotatedFields.class, "fake.fake"); - } - - @Test(expected = ValidationException.class) - public void testExtractInvalidIndex() { - @Index(value = "fake") - class Test implements Mappable { - private String test; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument().put("test", test); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - test = document.get("test", String.class); - } - } - - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(Test.class); - operations = new RepositoryOperations(Test.class, nitriteMapper, repository.getDocumentCollection()); - - operations.extractIndices(Test.class); + public void testToDocuments() { + Class type = Object.class; + assertEquals(3, + (new RepositoryOperations(type, new NitriteBuilderTest.CustomNitriteMapper(), mock(NitriteCollection.class))) + .toDocuments(new Object[]{"42", "42", "42"}).length); } @Test - public void testFindAnnotationFromInterface() { - NitriteMapper nitriteMapper = db.getConfig().nitriteMapper(); - ObjectRepository repository = db.getRepository(TestInterface.class); - operations = new RepositoryOperations(TestInterface.class, nitriteMapper, repository.getDocumentCollection()); - - Set indices = operations.extractIndices(TestInterface.class); - assertFalse(indices.isEmpty()); + public void testToDocuments2() { + assertNull((new RepositoryOperations(Object.class, null, mock(NitriteCollection.class))).toDocuments(null)); } - @Index(value = "value") - private interface Interface { - String getValue(); - } - - private static class ClassWithAnnotatedFields extends ClassWithNoAnnotatedFields { - @Deprecated - Long longValue; - private String stringValue; - @Deprecated - private String anotherValue; - - @Deprecated - public ClassWithAnnotatedFields() { - } - - @Override - public Document write(NitriteMapper mapper) { - return super.write(mapper) - .put("stringValue", stringValue) - .put("anotherValue", anotherValue) - .put("longValue", longValue); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - super.read(mapper, document); - stringValue = document.get("stringValue", String.class); - anotherValue = document.get("anotherValue", String.class); - longValue = document.get("longValue", Long.class); - } - } - - private static class ClassWithNoAnnotatedFields implements Mappable { - private String stringValue; - private Integer integer; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument().put("stringValue", stringValue) - .put("integer", integer); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - stringValue = document.get("stringValue", String.class); - integer = document.get("integer", Integer.class); - } - } - - private static class A extends B { - private String a; - private Long b; - private Integer c; - } - - private static class B implements Mappable { - String a; - private Short d; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("a", a) - .put("d", d); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - a = document.get("a", String.class); - d = document.get("d", Short.class); - } - } - - @Index(value = "testClass") - private static class ObjectWithNonComparableIndex implements Mappable { - private ObjectUtilsTest testClass; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument("testClass", testClass); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - testClass = document.get("testClass", ObjectUtilsTest.class); - } - } - - @Index(value = "testClass") - private static class ObjectWithIterableIndex implements Mappable { - private TestClass testClass; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("testClass", testClass.write(mapper)); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - TestClass tc = new TestClass(); - tc.read(mapper, document.get("testClass", Document.class)); - testClass = tc; - } + @Test + public void testToDocuments3() { + assertNull((new RepositoryOperations(Object.class, null, mock(NitriteCollection.class))) + .toDocuments(new Object[]{})); } - private static class TestClass implements Comparable, Iterable, Mappable { - @Override - public int compareTo(TestClass o) { - return 0; - } - - @Override - public Iterator iterator() { - return null; - } - - @Override - public Document write(NitriteMapper mapper) { - return createDocument(); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - - } + @Test + public void testToDocument() { + Class type = Object.class; + assertNull( + (new RepositoryOperations(type, new NitriteBuilderTest.CustomNitriteMapper(), mock(NitriteCollection.class))) + .toDocument("Object", true)); } - @InheritIndices - private static class TestInterface implements Interface, Mappable { - @Getter - private String value; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument().put("value", value); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - value = document.get("value", String.class); - } + @Test + public void testCreateUniqueFilter() { + Class type = Object.class; + assertThrows(NotIdentifiableException.class, () -> (new RepositoryOperations(type, + new NitriteBuilderTest.CustomNitriteMapper(), mock(NitriteCollection.class))).createUniqueFilter("Object")); } - @Index(value = "longValue") - @Index(value = "decimal") - private class TestObjectWithIndex implements Mappable { - private long longValue; - - private TestObject testObject; - - private BigDecimal decimal; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("longValue", longValue) - .put("testObject", testObject.write(mapper)) - .put("decimal", decimal.toPlainString()); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - longValue = document.get("longValue", Long.class); - testObject = new TestObject(); - testObject.read(mapper, document.get("testObject", Document.class)); - String decimalString = document.get("decimal", String.class); - decimal = new BigDecimal(decimalString); - } + @Test + public void testCreateIdFilter() { + Class type = Object.class; + assertThrows(NotIdentifiableException.class, () -> (new RepositoryOperations(type, + new NitriteBuilderTest.CustomNitriteMapper(), mock(NitriteCollection.class))).createIdFilter("Id")); } - @Index(value = "longValue") - private class TestObject implements Mappable { - private String stringValue; - - private Long longValue; - - @Override - public Document write(NitriteMapper mapper) { - return createDocument() - .put("stringValue", stringValue) - .put("longValue", longValue); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - stringValue = document.get("stringValue", String.class); - longValue = document.get("longValue", Long.class); - } + @Test + public void testFind() { + NitriteCollection nitriteCollection = mock(NitriteCollection.class); + RecordStream> recordStream = (RecordStream>) mock( + RecordStream.class); + when(nitriteCollection.find(any(), any())) + .thenReturn(new DocumentStream(recordStream, new ProcessorChain())); + Class type = Object.class; + RepositoryOperations repositoryOperations = new RepositoryOperations(type, + new NitriteBuilderTest.CustomNitriteMapper(), nitriteCollection); + Filter filter = mock(Filter.class); + FindOptions findOptions = new FindOptions(); + assertNull(repositoryOperations.find(filter, findOptions, Object.class).getFindPlan()); + verify(nitriteCollection).find(any(), any()); } } + diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/RepositorySearchTest.java b/nitrite/src/test/java/org/dizitart/no2/repository/RepositorySearchTest.java deleted file mode 100644 index 3f836505a..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/RepositorySearchTest.java +++ /dev/null @@ -1,604 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import lombok.Getter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.common.RecordStream; -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.exceptions.InvalidIdException; -import org.dizitart.no2.exceptions.NotIdentifiableException; -import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.data.*; -import org.junit.Test; - -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.List; - -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.$; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee. - */ -public class RepositorySearchTest extends BaseObjectRepositoryTest { - @Test - public void testFindWithOptions() { - Cursor cursor = employeeRepository.find().skipLimit(0, 1); - assertEquals(cursor.size(), 1); - assertNotNull(cursor.firstOrNull()); - } - - @Test - public void testEmployeeProjection() { - List employeeList = employeeRepository.find().toList(); - List subEmployeeList - = employeeRepository.find().project(SubEmployee.class).toList(); - - assertNotNull(employeeList); - assertNotNull(subEmployeeList); - - assertTrue(employeeList.size() > 0); - assertTrue(subEmployeeList.size() > 0); - - assertEquals(employeeList.size(), subEmployeeList.size()); - - for (int i = 0; i < subEmployeeList.size(); i++) { - Employee employee = employeeList.get(i); - SubEmployee subEmployee = subEmployeeList.get(i); - - assertEquals(employee.getEmpId(), subEmployee.getEmpId()); - assertEquals(employee.getJoinDate(), subEmployee.getJoinDate()); - assertEquals(employee.getAddress(), subEmployee.getAddress()); - } - - Cursor cursor = employeeRepository.find(); - assertNotNull(cursor.firstOrNull()); - assertNotNull(cursor.toString()); - assertEquals(cursor.toList().size(), employeeList.size()); - assertNotNull(cursor.firstOrNull()); - assertEquals(cursor.toList().size(), employeeList.size()); - } - - @Test - public void testEmptyResultProjection() { - employeeRepository.remove(ALL); - assertNull(employeeRepository.find().firstOrNull()); - - assertNull(employeeRepository.find(where("empId").eq(-1)) - .firstOrNull()); - } - - @Test - public void testGetById() { - ObjectRepository empRepo = db.getRepository(Employee.class); - Employee e1 = DataGenerator.generateEmployee(); - Employee e2 = DataGenerator.generateEmployee(); - Employee e3 = DataGenerator.generateEmployee(); - Employee e4 = DataGenerator.generateEmployee(); - - e1.setEmpId(1000000L); - e2.setEmpId(2000000L); - e3.setEmpId(3000000L); - e4.setEmpId(4000000L); - - empRepo.insert(e1, e2, e3, e4); - - Employee byId = empRepo.getById(2000000L); - assertEquals(byId, e2); - } - - @Test(expected = NotIdentifiableException.class) - public void testGetByIdNoId() { - ObjectRepository repository = db.getRepository(Note.class); - Note n1 = DataGenerator.randomNote(); - Note n2 = DataGenerator.randomNote(); - Note n3 = DataGenerator.randomNote(); - - assert n1 != null; - n1.setNoteId(1000000L); - assert n2 != null; - n2.setNoteId(2000000L); - assert n3 != null; - n3.setNoteId(3000000L); - - repository.insert(n1, n2, n3); - - repository.getById(2000000L); - } - - @Test(expected = InvalidIdException.class) - public void testGetByIdNullId() { - ObjectRepository empRepo = db.getRepository(Employee.class); - Employee e1 = DataGenerator.generateEmployee(); - Employee e2 = DataGenerator.generateEmployee(); - Employee e3 = DataGenerator.generateEmployee(); - Employee e4 = DataGenerator.generateEmployee(); - - e1.setEmpId(1000000L); - e2.setEmpId(2000000L); - e3.setEmpId(3000000L); - e4.setEmpId(4000000L); - - empRepo.insert(e1, e2, e3, e4); - - empRepo.getById(null); - } - - @Test(expected = InvalidIdException.class) - public void testGetByIdWrongType() { - ObjectRepository empRepo = db.getRepository(Employee.class); - Employee e1 = DataGenerator.generateEmployee(); - Employee e2 = DataGenerator.generateEmployee(); - Employee e3 = DataGenerator.generateEmployee(); - Employee e4 = DataGenerator.generateEmployee(); - - e1.setEmpId(1000000L); - e2.setEmpId(2000000L); - e3.setEmpId(3000000L); - e4.setEmpId(4000000L); - - empRepo.insert(e1, e2, e3, e4); - - Employee byId = empRepo.getById("employee"); - assertNull(byId); - } - - @Test - public void testEqualFilterById() { - Employee employee = employeeRepository.find().firstOrNull(); - long empId = employee.getEmpId(); - Employee emp = employeeRepository.find(where("empId").eq(empId)) - .project(Employee.class).firstOrNull(); - assertEquals(employee, emp); - } - - @Test - public void testEqualFilter() { - Employee employee = employeeRepository.find() - .firstOrNull(); - - Employee emp = employeeRepository.find(where("joinDate").eq(employee.getJoinDate())) - .project(Employee.class) - .firstOrNull(); - assertEquals(employee, emp); - } - - @Test - public void testStringEqualFilter() { - ObjectRepository repository = db.getRepository(ProductScore.class); - - ProductScore object = new ProductScore(); - object.setProduct("test"); - object.setScore(1); - repository.insert(object); - - object = new ProductScore(); - object.setProduct("test"); - object.setScore(2); - repository.insert(object); - - object = new ProductScore(); - object.setProduct("another-test"); - object.setScore(3); - repository.insert(object); - - assertEquals(repository.find(where("product").eq("test")).size(), 2); - } - - @Test - public void testAndFilter() { - Employee emp = employeeRepository.find().firstOrNull(); - - long id = emp.getEmpId(); - String address = emp.getAddress(); - Date joinDate = emp.getJoinDate(); - - Employee employee = employeeRepository.find( - where("empId").eq(id) - .and( - where("address").regex(address) - .and( - where("joinDate").eq(joinDate)))).firstOrNull(); - - assertEquals(emp, employee); - } - - @Test - public void testOrFilter() { - Employee emp = employeeRepository.find().firstOrNull(); - long id = emp.getEmpId(); - - Employee employee = employeeRepository.find( - where("empId").eq(id) - .or( - where("address").regex("n/a") - .or( - where("joinDate").eq(null)))).firstOrNull(); - - assertEquals(emp, employee); - } - - @Test - public void testNotFilter() { - Employee emp = employeeRepository.find().firstOrNull(); - long id = emp.getEmpId(); - - Employee employee = employeeRepository.find( - where("empId").eq(id).not()).firstOrNull(); - assertNotEquals(emp, employee); - } - - @Test - public void testGreaterFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Ascending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").gt(id)) - .toList(); - - assertFalse(employeeList.contains(emp)); - assertEquals(employeeList.size(), 9); - } - - @Test - public void testGreaterEqualFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Ascending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").gte(id)) - .toList(); - - assertTrue(employeeList.contains(emp)); - assertEquals(employeeList.size(), 10); - } - - @Test - public void testLesserThanFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Descending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").lt(id)) - .toList(); - - assertFalse(employeeList.contains(emp)); - assertEquals(employeeList.size(), 9); - } - - @Test - public void testLesserEqualFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Descending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").lte(id)) - .toList(); - - assertTrue(employeeList.contains(emp)); - assertEquals(employeeList.size(), 10); - } - - @Test - public void testTextFilter() { - Employee emp = employeeRepository.find().firstOrNull(); - String text = emp.getEmployeeNote().getText(); - - List employeeList = employeeRepository.find(where("employeeNote.text").text(text)) - .toList(); - - assertTrue(employeeList.contains(emp)); - } - - @Test - public void testRegexFilter() { - RecordStream employees = employeeRepository.find(); - int count = employees.toList().size(); - - List employeeList = employeeRepository.find(where("employeeNote.text").regex(".*")) - .toList(); - - assertEquals(employeeList.size(), count); - } - - @Test - public void testInFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Descending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").in(id, id - 1, id - 2)) - .toList(); - - assertTrue(employeeList.contains(emp)); - assertEquals(employeeList.size(), 3); - - employeeList = employeeRepository.find(where("empId").in(id - 1, id - 2)).toList(); - assertEquals(employeeList.size(), 2); - } - - @Test - public void testNotInFilter() { - Employee emp = employeeRepository.find().sort("empId", SortOrder.Descending).firstOrNull(); - long id = emp.getEmpId(); - - List employeeList = employeeRepository.find(where("empId").notIn(id, id - 1, id - 2)) - .toList(); - - assertFalse(employeeList.contains(emp)); - assertEquals(employeeList.size(), 7); - - employeeList = employeeRepository.find(where("empId").notIn(id - 1, id - 2)).toList(); - assertEquals(employeeList.size(), 8); - } - - @Test - public void testElemMatchFilter() { - final ProductScore score1 = new ProductScore("abc", 10); - final ProductScore score2 = new ProductScore("abc", 8); - final ProductScore score3 = new ProductScore("abc", 7); - final ProductScore score4 = new ProductScore("xyz", 5); - final ProductScore score5 = new ProductScore("xyz", 7); - final ProductScore score6 = new ProductScore("xyz", 8); - - ObjectRepository repository = db.getRepository(ElemMatch.class); - ElemMatch e1 = new ElemMatch() {{ - setId(1); - setStrArray(new String[]{"a", "b"}); - setProductScores(new ProductScore[]{score1, score4}); - }}; - ElemMatch e2 = new ElemMatch() {{ - setId(2); - setStrArray(new String[]{"d", "e"}); - setProductScores(new ProductScore[]{score2, score5}); - }}; - ElemMatch e3 = new ElemMatch() {{ - setId(3); - setStrArray(new String[]{"a", "f"}); - setProductScores(new ProductScore[]{score3, score6}); - }}; - - repository.insert(e1, e2, e3); - - List elements = repository.find( - where("productScores").elemMatch( - where("product").eq("xyz") - .and(where("score").gte(8)))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("score").lte(8).not())).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("product").eq("xyz") - .or(where("score").gte(8)))).toList(); - assertEquals(elements.size(), 3); - - elements = repository.find( - where("productScores").elemMatch( - where("product").eq("xyz"))).toList(); - assertEquals(elements.size(), 3); - - elements = repository.find( - where("productScores").elemMatch( - where("score").gte(10))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("score").gt(8))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("score").lt(7))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("score").lte(7))).toList(); - assertEquals(elements.size(), 3); - - elements = repository.find( - where("productScores").elemMatch( - where("score").in(7, 8))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find( - where("productScores").elemMatch( - where("score").notIn(7, 8))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find( - where("productScores").elemMatch( - where("product").regex("xyz"))).toList(); - assertEquals(elements.size(), 3); - - elements = repository.find(where("strArray").elemMatch($.eq("a"))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find( - where("strArray").elemMatch( - $.eq("a") - .or($.eq("f") - .or($.eq("b"))).not())).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find(where("strArray").elemMatch($.gt("e"))).toList(); - assertEquals(elements.size(), 1); - - elements = repository.find(where("strArray").elemMatch($.gte("e"))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find(where("strArray").elemMatch($.lte("b"))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find(where("strArray").elemMatch($.lt("a"))).toList(); - assertEquals(elements.size(), 0); - - elements = repository.find(where("strArray").elemMatch($.in("a", "f"))).toList(); - assertEquals(elements.size(), 2); - - elements = repository.find(where("strArray").elemMatch($.regex("a"))).toList(); - assertEquals(elements.size(), 2); - } - - @Test - public void testFilterAll() { - ObjectRepository repository = db.getRepository(ElemMatch.class); - Cursor cursor = repository.find(ALL); - assertNotNull(cursor); - assertEquals(cursor.size(), 0); - - repository.insert(new ElemMatch()); - cursor = repository.find(ALL); - assertNotNull(cursor); - assertEquals(cursor.size(), 1); - } - - @Test - public void testEqualsOnTextIndex() { - PersonEntity p1 = new PersonEntity("jhonny"); - PersonEntity p2 = new PersonEntity("jhonny"); - PersonEntity p3 = new PersonEntity("jhonny"); - - ObjectRepository repository = db.getRepository(PersonEntity.class); - repository.insert(p1); - repository.insert(p2); - repository.insert(p3); - - List sameNamePeople = repository.find(where("name").eq("jhonny")).toList(); - assertEquals(sameNamePeople.size(), 3); - - sameNamePeople = repository.find(where("name").eq("JHONNY")).toList(); - assertEquals(sameNamePeople.size(), 0); - - sameNamePeople = repository.find(where("name").text("jhonny")).toList(); - assertEquals(sameNamePeople.size(), 3); - - sameNamePeople = repository.find(where("name").text("JHONNY")).toList(); - assertEquals(sameNamePeople.size(), 3); - - sameNamePeople = repository.find(where("name").eq("jhon*")).toList(); - assertEquals(sameNamePeople.size(), 0); - - sameNamePeople = repository.find(where("name").text("jhon*")).toList(); - assertEquals(sameNamePeople.size(), 3); - } - - @Test - public void testIssue62() { - PersonEntity p1 = new PersonEntity("abcd"); - p1.setStatus("Married"); - - PersonEntity p2 = new PersonEntity("efgh"); - p2.setStatus("Married"); - - PersonEntity p3 = new PersonEntity("ijkl"); - p3.setStatus("Un-Married"); - - ObjectRepository repository = db.getRepository(PersonEntity.class); - repository.insert(p1); - repository.insert(p2); - repository.insert(p3); - - Filter married = where("status").eq("Married"); - - assertEquals(repository.find(married).size(), 2); - assertEquals(repository.find(married).sort("status", SortOrder.Descending).size(), 2); - - assertEquals(repository.find().sort("status", SortOrder.Descending).firstOrNull().getStatus(), "Un-Married"); - - assertEquals(repository.find().sort("status", SortOrder.Ascending).size(), 3); - assertEquals(repository.find().sort("status", SortOrder.Ascending).firstOrNull().getStatus(), "Married"); - } - - @Test - public void testRepeatableIndexAnnotation() { - ObjectRepository repo = db.getRepository(RepeatableIndexTest.class); - RepeatableIndexTest first = new RepeatableIndexTest(); - first.setAge(12); - first.setFirstName("fName"); - first.setLastName("lName"); - repo.insert(first); - - assertTrue(repo.hasIndex("firstName")); - assertTrue(repo.hasIndex("age")); - assertTrue(repo.hasIndex("lastName")); - - assertEquals(repo.find(where("age").eq(12)).firstOrNull(), first); - } - - @Test - public void testIdSet() { - Cursor employees = employeeRepository.find().sort("empId", SortOrder.Ascending); - assertEquals(employees.size(), 10); - } - - @Test - public void testBetweenFilter() { - @Getter - class TestData implements Mappable { - private Date age; - - public TestData(Date age) { - this.age = age; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("age", age); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - age = document.get("age", Date.class); - } - } - - TestData data1 = new TestData(new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime()); - TestData data2 = new TestData(new GregorianCalendar(2021, Calendar.FEBRUARY, 12).getTime()); - TestData data3 = new TestData(new GregorianCalendar(2022, Calendar.MARCH, 13).getTime()); - TestData data4 = new TestData(new GregorianCalendar(2023, Calendar.APRIL, 14).getTime()); - TestData data5 = new TestData(new GregorianCalendar(2024, Calendar.MAY, 15).getTime()); - TestData data6 = new TestData(new GregorianCalendar(2025, Calendar.JUNE, 16).getTime()); - - ObjectRepository repository = db.getRepository(TestData.class); - repository.insert(data1, data2, data3, data4, data5, data6); - - Cursor cursor = repository.find(where("age").between( - new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), - new GregorianCalendar(2025, Calendar.JUNE, 16).getTime())); - assertEquals(cursor.size(), 6); - - cursor = repository.find(where("age").between( - new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), - new GregorianCalendar(2025, Calendar.JUNE, 16).getTime(), false)); - assertEquals(cursor.size(), 4); - - cursor = repository.find(where("age").between( - new GregorianCalendar(2020, Calendar.JANUARY, 11).getTime(), - new GregorianCalendar(2025, Calendar.JUNE, 16).getTime(), false, true)); - assertEquals(cursor.size(), 5); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/UnAnnotatedObjectTest.java b/nitrite/src/test/java/org/dizitart/no2/repository/UnAnnotatedObjectTest.java deleted file mode 100644 index 45a55d9b4..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/UnAnnotatedObjectTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - - -import org.dizitart.no2.common.SortOrder; -import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.repository.data.ClassA; -import org.dizitart.no2.repository.data.ClassC; -import org.junit.Test; - -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -/** - * @author Anindya Chatterjee. - */ -public class UnAnnotatedObjectTest extends BaseObjectRepositoryTest { - - @Test - @SuppressWarnings("unchecked") - public void testFind() { - Cursor cursor = aObjectRepository.find(); - assertEquals(cursor.size(), 10); - assertFalse(cursor.isEmpty()); - - IndexOptions indexOptions = new IndexOptions(); - indexOptions.setIndexType(IndexType.Unique); - aObjectRepository.createIndex("b.number", indexOptions); - - cursor = aObjectRepository.find(where("b.number").eq(160).not()). - sort("b.number", SortOrder.Ascending).skipLimit(0, 10); - - System.out.println("Available - " + !cursor.isEmpty()); - System.out.println("Total Size - " + cursor.size()); - - Iterable findRecord = cursor.project(ClassA.class); - for (ClassA classA : findRecord) { - System.out.println(classA); - } - - cursor = aObjectRepository.find(where("b.number").eq(160).not()). - sort("b.number", SortOrder.Descending).skipLimit(2, 7); - - System.out.println("Available - " + !cursor.isEmpty()); - System.out.println("Total Size - " + cursor.size()); - - findRecord = cursor.project(ClassA.class); - for (ClassA classA : findRecord) { - System.out.println(classA); - } - - cursor = cObjectRepository.find(where("id").gt(900)). - sort("id", SortOrder.Descending).skipLimit(2, 7); - System.out.println("Available - " + !cursor.isEmpty()); - System.out.println("Total Size - " + cursor.size()); - - Iterable findRecordC = cursor.project(ClassC.class); - for (ClassC classC : findRecordC) { - System.out.println(classC); - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/UniversalTextTokenizerTest.java b/nitrite/src/test/java/org/dizitart/no2/repository/UniversalTextTokenizerTest.java deleted file mode 100644 index 433e3ccc1..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/UniversalTextTokenizerTest.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository; - -import org.dizitart.no2.Nitrite; -import org.dizitart.no2.NitriteBuilder; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.index.NitriteTextIndexer; -import org.dizitart.no2.index.fulltext.Languages; -import org.dizitart.no2.index.fulltext.UniversalTextTokenizer; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.IOException; - -import static org.dizitart.no2.DbTestOperations.getRandomTempDbFile; -import static org.dizitart.no2.filters.Filter.ALL; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.module.NitriteModule.module; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -/** - * @author Anindya Chatterjee - */ -public class UniversalTextTokenizerTest extends BaseObjectRepositoryTest { - private final String fileName = getRandomTempDbFile(); - private ObjectRepository textRepository; - - @Before - @Override - public void setUp() { - openDb(); - - textRepository = db.getRepository(TextData.class); - - for (int i = 0; i < 10; i++) { - TextData data = new TextData(); - data.id = i; - if (i % 2 == 0) { - data.text = "তারা বলল, “এস আমরা আমাদের জন্যে এক বড় শহর বানাই| আর এমন একটি উঁচু স্তম্ভ বানাই " + - "যা আকাশ স্পর্শ করবে| তাহলে আমরা বিখ্যাত হব এবং এটা আমাদের এক সঙ্গে ধরে রাখবে| সারা পৃথিবীতে " + - "আমরা ছড়িয়ে থাকব না|”"; - } else if (i % 3 == 0) { - data.text = "部汁楽示時葉没式将場参右属。覧観将者雄日語山銀玉襲政著約域費。新意虫跡更味株付安署審完顔団。" + - "困更表転定一史賀面政巣迎文学豊税乗。白間接特時京転閉務講封新内。側流効表害場測投活聞秀職探画労。" + - "福川順式極木注美込行警検直性禁遅。土一詳非物質紙姿漢人内池銀周街躍澹二。平討聞述並時全経詳業映回作朝送恵時。"; - } else if (i % 5 == 0) { - data.text = " أقبل لسفن العالم، في أما, بـ بال أملاً الثالث،. الذود بالرّد الثالث، مع" + - " قام, كردة الضغوط الإمداد أن وصل. ٠٨٠٤ عُقر انتباه يكن قد, أن زهاء وفنلندا بال. لان ما يقوم المعاهدات," + - " بـ بخطوط استعملت عدد. صفحة لفشل ولاتّساع لم قام, في مكثّفة الكونجرس جعل, الثالث، واقتصار دون ان.\n"; - } else { - data.text = "Lorem ipsum dolor sit amet, nobis audire perpetua eu sea. Te semper causae " + - "efficiantur per. Qui affert dolorum at. Mel tale constituto interesset in."; - } - textRepository.insert(data); - } - } - - @After - @Override - public void clear() throws IOException { - if (textRepository != null && !textRepository.isDropped()) { - textRepository.remove(ALL); - } - - if (db != null) { - db.commit(); - db.close(); - } - } - - private void openDb() { - NitriteBuilder nitriteBuilder = Nitrite.builder() - .fieldSeparator("."); - - UniversalTextTokenizer tokenizer; - if (isProtected) { - tokenizer = new UniversalTextTokenizer(Languages.Bengali, Languages.Chinese, Languages.English); - } else { - tokenizer = new UniversalTextTokenizer(Languages.ALL); - } - nitriteBuilder.loadModule(module(new NitriteTextIndexer(tokenizer))); - - if (isProtected) { - db = nitriteBuilder.openOrCreate("test-user", "test-password"); - } else { - db = nitriteBuilder.openOrCreate(); - } - } - - @Test - public void testUniversalFullTextIndexing() { - Cursor cursor = textRepository.find(where("text").text("Lorem")); - assertEquals(cursor.size(), 2); - for (TextData data : cursor) { - System.out.println("Id for English text -> " + data.id); - if (data.id % 2 == 0 || data.id % 3 == 0 || data.id % 5 == 0) { - fail(); - } - } - - cursor = textRepository.find(where("text").text("শহর")); - assertEquals(cursor.size(), 5); - for (TextData data : cursor) { - System.out.println("Id for Bengali text -> " + data.id); - if (data.id % 2 != 0) { - fail(); - } - } - - cursor = textRepository.find(where("text").text("転閉")); - assertEquals(cursor.size(), 0); - cursor = textRepository.find(where("text").text("*転閉*")); - assertEquals(cursor.size(), 2); - for (TextData data : cursor) { - System.out.println("Id for Chinese text -> " + data.id); - if (data.id % 3 != 0) { - fail(); - } - } - - cursor = textRepository.find(where("text").text("أقبل")); - if (isProtected) { - assertEquals(cursor.size(), 1); - for (TextData data : cursor) { - System.out.println("Id for Arabic text -> " + data.id); - if (data.id % 5 != 0) { - fail(); - } - } - } else { - // أقبل eliminated as stop word - assertEquals(cursor.size(), 0); - } - } - - @Indices( - @Index(value = "text", type = IndexType.Fulltext) - ) - public static class TextData implements Mappable { - public int id; - public String text; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("id", id) - .put("text", text); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Integer.class); - text = document.get("text", String.class); - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/ChildClass.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/ChildClass.java deleted file mode 100644 index f6c2fabb5..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/ChildClass.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.InheritIndices; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@InheritIndices -public class ChildClass extends ParentClass { - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return super.write(mapper).put("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - super.read(mapper, document); - name = document.get("name", String.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/ClassA.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/ClassA.java deleted file mode 100644 index 4cdce3acc..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/ClassA.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.util.UUID; - -@EqualsAndHashCode -@ToString -public class ClassA implements Mappable { - @Getter - @Setter - private ClassB classB; - @Getter - @Setter - private UUID uid; - @Getter - @Setter - private String string; - @Getter - @Setter - private byte[] blob; - - public static ClassA create(int seed) { - ClassB classB = ClassB.create(seed); - ClassA classA = new ClassA(); - classA.classB = classB; - classA.uid = new UUID(seed, seed + 50); - classA.string = Integer.toHexString(seed); - classA.blob = new byte[]{(byte) seed}; - return classA; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("classB", classB != null ? classB.write(mapper) : null) - .put("uid", uid) - .put("string", string) - .put("blob", blob); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - if (document.get("classB") != null) { - classB = new ClassB(); - classB.read(mapper, document.get("classB", Document.class)); - } - uid = document.get("uid", UUID.class); - string = document.get("string", String.class); - blob = document.get("blob", byte[].class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/ClassB.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/ClassB.java deleted file mode 100644 index 9be7793e8..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/ClassB.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -@EqualsAndHashCode -@ToString -class ClassB implements Comparable, Mappable { - @Getter - @Setter - private int number; - @Getter - @Setter - private String text; - - static ClassB create(int seed) { - ClassB classB = new ClassB(); - classB.setNumber(seed + 100); - classB.setText(Integer.toBinaryString(seed)); - return classB; - } - - @Override - public int compareTo(ClassB o) { - return Integer.compare(number, o.number); - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("number", number) - .put("text", text); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - number = document.get("number", Integer.class); - text = document.get("text", String.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/ClassC.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/ClassC.java deleted file mode 100644 index 4402a7109..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/ClassC.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -@EqualsAndHashCode -@ToString -public class ClassC implements Mappable { - @Getter - @Setter - private long id; - @Getter - @Setter - private double digit; - @Getter - @Setter - private ClassA parent; - - public static ClassC create(int seed) { - ClassC classC = new ClassC(); - classC.id = seed * 5000; - classC.digit = seed * 69.65; - classC.parent = ClassA.create(seed); - return classC; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("id", id) - .put("digit", digit) - .put("parent", parent != null ? parent.write(mapper) : null); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Long.class); - digit = document.get("digit", Double.class); - if (document.get("parent") != null) { - parent = new ClassA(); - parent.read(mapper, document.get("parent", Document.class)); - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/Company.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/Company.java deleted file mode 100644 index 8171c4bff..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/Company.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; -import org.dizitart.no2.repository.annotations.Indices; - -import java.io.Serializable; -import java.util.Date; -import java.util.List; -import java.util.Map; - -/** - * @author Anindya Chatterjee. - */ -@ToString -@EqualsAndHashCode -@Indices({ - @Index(value = "companyName") -}) -public class Company implements Serializable, Mappable { - @Id - @Getter - @Setter - private Long companyId; - - @Getter - @Setter - private String companyName; - - @Getter - @Setter - private Date dateCreated; - - @Getter - @Setter - private List departments; - - @Getter - @Setter - private Map> employeeRecord; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("companyId", companyId) - .put("companyName", companyName) - .put("dateCreated", dateCreated) - .put("departments", departments) - .put("employeeRecord", employeeRecord); - } - - @Override - @SuppressWarnings("unchecked") - public void read(NitriteMapper mapper, Document document) { - companyId = document.get("companyId", Long.class); - companyName = document.get("companyName", String.class); - dateCreated = document.get("dateCreated", Date.class); - departments = document.get("departments", List.class); - employeeRecord = document.get("employeeRecord", Map.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/DataGenerator.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/DataGenerator.java deleted file mode 100644 index c0a0352be..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/DataGenerator.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @author Anindya Chatterjee. - */ -public class DataGenerator { - private static final Random random = new Random(System.currentTimeMillis()); - private static final AtomicInteger counter = new AtomicInteger(random.nextInt()); - - private DataGenerator() {} - - public static Company generateCompanyRecord() { - Company company = new Company(); - company.setCompanyId(System.nanoTime() + counter.incrementAndGet()); - company.setCompanyName(randomCompanyName()); - company.setDateCreated(randomDate()); - List departments = departments(); - company.setDepartments(departments); - - Map> employeeRecord = new HashMap<>(); - for (String department : departments) { - employeeRecord.put(department, - generateEmployeeRecords(company, random.nextInt(20))); - } - company.setEmployeeRecord(employeeRecord); - return company; - } - - private static List generateEmployeeRecords(Company company, int count) { - List employeeList = new ArrayList<>(); - for (int i = 0; i < count; i++) { - Employee employee = generateEmployee(); - employee.setCompany(company); - employeeList.add(employee); - } - return employeeList; - } - - public static Employee generateEmployee() { - Employee employee = new Employee(); - employee.setEmpId(System.nanoTime() + counter.incrementAndGet()); - employee.setJoinDate(randomDate()); - employee.setAddress(UUID.randomUUID().toString().replace('-', ' ')); - - byte[] blob = new byte[random.nextInt(8000)]; - random.nextBytes(blob); - employee.setBlob(blob); - employee.setEmployeeNote(randomNote()); - - return employee; - } - - private static Date randomDate() { - return new Date(-946771200000L + - (Math.abs(random.nextLong()) % (70L * 365 * 24 * 60 * 60 * 1000))); - } - - public static Note randomNote() { - InputStream inputStream = ClassLoader.getSystemResourceAsStream("test.text"); - - assert inputStream != null; - try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) { - String strLine; - long line = random.nextInt(49); - int count = 0; - while ((strLine = br.readLine()) != null) { - if (count == line) { - Note note = new Note(); - note.setNoteId(line); - note.setText(strLine); - return note; - } - count++; - } - } catch (IOException e) { - // ignore - } - // ignore - return null; - } - - private static String randomCompanyName() { - InputStream inputStream = ClassLoader.getSystemResourceAsStream("english.stop"); - - assert inputStream != null; - try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) { - String strLine; - int line = random.nextInt(570); - int count = 0; - while ((strLine = br.readLine()) != null) { - if (count == line) { - return strLine + System.nanoTime() + " inc."; - } - count++; - } - } catch (IOException e) { - // ignore - } - // ignore - return null; - } - - private static List departments() { - return new ArrayList() {{ - add("dev"); - add("hr"); - add("qa"); - add("dev-ops"); - add("sales"); - add("marketing"); - add("design"); - add("support"); - }}; - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/ElemMatch.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/ElemMatch.java deleted file mode 100644 index dd0042ff1..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/ElemMatch.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author Anindya Chatterjee - */ -@Data -public class ElemMatch implements Mappable { - private long id; - private String[] strArray; - private ProductScore[] productScores; - - @Override - public Document write(NitriteMapper mapper) { - List list = new ArrayList<>(); - if (productScores != null) { - for (ProductScore productScore : productScores) { - Document document = productScore.write(mapper); - list.add(document); - } - } - - return Document.createDocument("id", id) - .put("strArray", strArray) - .put("productScores", list); - } - - @Override - @SuppressWarnings("unchecked") - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Long.class); - strArray = document.get("strArray", String[].class); - List list = document.get("productScores", List.class); - if (list != null) { - productScores = new ProductScore[list.size()]; - for (int i = 0; i < list.size(); i++) { - productScores[i] = new ProductScore(); - productScores[i].read(mapper, list.get(i)); - } - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/Employee.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/Employee.java deleted file mode 100644 index 552adde62..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/Employee.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; - -import java.io.Serializable; -import java.util.Date; - -/** - * @author Anindya Chatterjee. - */ -@ToString -@EqualsAndHashCode -@Index(value = "joinDate", type = IndexType.NonUnique) -@Index(value = "address", type = IndexType.Fulltext) -@Index(value = "employeeNote.text", type = IndexType.Fulltext) -public class Employee implements Serializable, Mappable { - @Id - @Getter - @Setter - private Long empId; - - @Getter - @Setter - private Date joinDate; - - @Getter - @Setter - private String address; - - @Getter - @Setter - private transient Company company; - - @Getter - @Setter - private byte[] blob; - - @Getter - @Setter - private Note employeeNote; - - public Employee() { - } - - public Employee(Employee copy) { - empId = copy.empId; - joinDate = copy.joinDate; - address = copy.address; - company = copy.company; - blob = copy.blob; - employeeNote = copy.employeeNote; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("empId", empId) - .put("joinDate", joinDate) - .put("address", address) - .put("blob", blob) - .put("employeeNote", employeeNote != null ? employeeNote.write(mapper) : null); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - empId = document.get("empId", Long.class); - joinDate = document.get("joinDate", Date.class); - address = document.get("address", String.class); - blob = document.get("blob", byte[].class); - - if (document.get("employeeNote") != null) { - employeeNote = new Note(); - employeeNote.read(mapper, document.get("employeeNote", Document.class)); - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/Note.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/Note.java deleted file mode 100644 index 24dacae30..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/Note.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.io.Serializable; - -/** - * @author Anindya Chatterjee. - */ -@EqualsAndHashCode -public class Note implements Serializable, Mappable { - @Getter - @Setter - private Long noteId; - @Getter - @Setter - private String text; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument().put("noteId", noteId).put("text", text); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - noteId = document.get("noteId", Long.class); - text = document.get("text", String.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/ParentClass.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/ParentClass.java deleted file mode 100644 index 296655f29..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/ParentClass.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; - -import java.util.Date; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@Index(value = "date") -public class ParentClass extends SuperDuperClass { - @Id - protected Long id; - private Date date; - - @Override - public Document write(NitriteMapper mapper) { - return super.write(mapper) - .put("id", id) - .put("date", date); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - super.read(mapper, document); - id = document.get("id", Long.class); - date = document.get("date", Date.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/PersonEntity.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/PersonEntity.java deleted file mode 100644 index 0e1a306a6..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/PersonEntity.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Entity; -import org.dizitart.no2.repository.annotations.Id; -import org.dizitart.no2.repository.annotations.Index; - -import java.util.Date; -import java.util.UUID; - -/** - * @author Anindya Chatterjee - */ -@Data -@Entity(value = "MyPerson", indices = { - @Index(value = "name", type = IndexType.Fulltext), - @Index(value = "status", type = IndexType.NonUnique) -}) -public class PersonEntity implements Mappable { - @Id - private String uuid; - private String name; - private String status; - private PersonEntity friend; - private Date dateCreated; - - public PersonEntity() { - this.uuid = UUID.randomUUID().toString(); - this.dateCreated = new Date(); - } - - public PersonEntity(String name) { - this.uuid = UUID.randomUUID().toString(); - this.name = name; - this.dateCreated = new Date(); - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("uuid", uuid) - .put("name", name) - .put("status", status) - .put("friend", friend != null ? friend.write(mapper) : null) - .put("dateCreated", dateCreated); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - if (document != null) { - uuid = document.get("uuid", String.class); - name = document.get("name", String.class); - status = document.get("status", String.class); - dateCreated = document.get("dateCreated", Date.class); - friend = new PersonEntity(); - friend.read(mapper, document.get("friend", Document.class)); - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/ProductScore.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/ProductScore.java deleted file mode 100644 index 9075ae5f5..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/ProductScore.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -public class ProductScore implements Mappable { - private String product; - private int score; - - public ProductScore() { - } - - public ProductScore(String product, int score) { - this.product = product; - this.score = score; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("product", product) - .put("score", score); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - product = document.get("product", String.class); - score = document.get("score", Integer.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/RepeatableIndexTest.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/RepeatableIndexTest.java deleted file mode 100644 index 85bfe165d..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/RepeatableIndexTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Index; - -/** - * @author Anindya Chatterjee - */ -@Data -@Index(value = "firstName") -@Index(value = "age", type = IndexType.NonUnique) -@Index(value = "lastName", type = IndexType.Fulltext) -public class RepeatableIndexTest implements Mappable { - private String firstName; - private Integer age; - private String lastName; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("firstName", firstName) - .put("age", age) - .put("lastName", lastName); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - firstName = document.get("firstName", String.class); - age = document.get("age", Integer.class); - lastName = document.get("lastName", String.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/StressRecord.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/StressRecord.java deleted file mode 100644 index 471ae0964..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/StressRecord.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class StressRecord implements Mappable { - private String firstName; - private boolean processed; - private String lastName; - private boolean failed; - private String notes; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument().put("firstName", firstName) - .put("processed", processed) - .put("lastName", lastName) - .put("failed", failed) - .put("notes", notes); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - firstName = document.get("firstName", String.class); - processed = document.get("processed", Boolean.class); - lastName = document.get("lastName", String.class); - failed = document.get("failed", Boolean.class); - notes = document.get("notes", String.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/SubEmployee.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/SubEmployee.java deleted file mode 100644 index 8c845a616..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/SubEmployee.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.util.Date; - -/** - * @author Anindya Chatterjee. - */ -@EqualsAndHashCode -public class SubEmployee implements Mappable { - @Getter - @Setter - private Long empId; - - @Getter - @Setter - private Date joinDate; - - @Getter - @Setter - private String address; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("empId", empId) - .put("joinDate", joinDate) - .put("address", address); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - empId = document.get("empId", Long.class); - joinDate = document.get("joinDate", Date.class); - address = document.get("address", String.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/SuperDuperClass.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/SuperDuperClass.java deleted file mode 100644 index 26f7e783f..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/SuperDuperClass.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Index; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@Index(value = "text", type = IndexType.Fulltext) -public class SuperDuperClass implements Mappable { - private String text; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("text", text); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - text = document.get("text", String.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithCircularReference.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/WithCircularReference.java deleted file mode 100644 index ea80f05ca..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithCircularReference.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithCircularReference { - private String name; - private WithCircularReference parent; -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithClassField.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/WithClassField.java deleted file mode 100644 index ebed1725b..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithClassField.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithClassField implements Mappable { - @Id - private String name; - private Class clazz; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name) - .put("clazz", clazz); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - clazz = document.get("clazz", Class.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithCustomConstructor.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/WithCustomConstructor.java deleted file mode 100644 index 3f611bacd..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithCustomConstructor.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithCustomConstructor { - private String name; - private long number; - - public WithCustomConstructor(String name, long number) { - this.name = name; - this.number = number; - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithDateId.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/WithDateId.java deleted file mode 100644 index 16d113a2c..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithDateId.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.util.Date; - -/** - * @author Anindya Chatterjee - */ -@Getter -@Setter -@EqualsAndHashCode -public class WithDateId implements Mappable { - private Date id; - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name) - .put("id", id); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - id = document.get("id", Date.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithEmptyStringId.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/WithEmptyStringId.java deleted file mode 100644 index 9364a46d8..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithEmptyStringId.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithEmptyStringId implements Mappable { - @Id - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithFinalField.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/WithFinalField.java deleted file mode 100644 index 5e2f50044..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithFinalField.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.exceptions.ObjectMappingException; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; - -/** - * @author Anindya Chatterjee. - */ -@Getter -public class WithFinalField implements Mappable { - private final long number; - @Setter - private String name; - - public WithFinalField() { - number = 2; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("name", name) - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - try { - Field field = getClass().getDeclaredField("number"); - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); - field.set(this, document.get("number", Long.class)); - } catch (Exception e) { - throw new ObjectMappingException("failed to set value"); - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithNitriteId.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/WithNitriteId.java deleted file mode 100644 index f219dd263..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithNitriteId.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Data; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteId; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee - */ -@Data -public class WithNitriteId implements Mappable { - @Id - public NitriteId idField; - public String name; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("idField", idField) - .put("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - idField = document.get("idField", NitriteId.class); - name = document.get("name", String.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithNullId.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/WithNullId.java deleted file mode 100644 index ecd49c64f..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithNullId.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithNullId implements Mappable { - @Id - private String name; - private long number; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("name", name) - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - number = document.get("number", Long.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithObjectId.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/WithObjectId.java deleted file mode 100644 index 295428867..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithObjectId.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithObjectId implements Mappable { - @Id - private WithOutId withOutId; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("withOutId", withOutId); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - withOutId = document.get("withOutId", WithOutId.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithOutGetterSetter.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/WithOutGetterSetter.java deleted file mode 100644 index 607967bd3..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithOutGetterSetter.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.EqualsAndHashCode; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@EqualsAndHashCode -public class WithOutGetterSetter implements Mappable { - private String name; - private long number; - - public WithOutGetterSetter() { - name = "test"; - number = 2; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name) - .put("number", number); - - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - number = document.get("number", Long.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithOutId.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/WithOutId.java deleted file mode 100644 index 08cad426e..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithOutId.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithOutId implements Comparable, Mappable { - private String name; - private long number; - - @Override - public int compareTo(WithOutId o) { - return Long.compare(number, o.number); - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("name", name) - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - number = document.get("number", Long.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithPrivateConstructor.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/WithPrivateConstructor.java deleted file mode 100644 index 25df54331..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithPrivateConstructor.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.EqualsAndHashCode; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; - -/** - * @author Anindya Chatterjee. - */ -@EqualsAndHashCode -public class WithPrivateConstructor implements Mappable { - private String name; - private long number; - - private WithPrivateConstructor() { - name = "test"; - number = 2; - } - - public static WithPrivateConstructor create(final String name, final long number) { - WithPrivateConstructor obj = new WithPrivateConstructor(); - obj.number = number; - obj.name = name; - return obj; - } - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name) - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - number = document.get("number", Long.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithPublicField.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/WithPublicField.java deleted file mode 100644 index 05c0ffc9c..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithPublicField.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -public class WithPublicField implements Mappable { - @Id - public String name; - public long number; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("name", name) - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - name = document.get("name", String.class); - number = document.get("number", Long.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithTransientField.java b/nitrite/src/test/java/org/dizitart/no2/repository/data/WithTransientField.java deleted file mode 100644 index 9642b8f30..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/repository/data/WithTransientField.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.repository.data; - -import lombok.Getter; -import lombok.Setter; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Getter -@Setter -public class WithTransientField implements Mappable { - private transient String name; - @Id - private long number; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument() - .put("number", number); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - number = document.get("number", Long.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/store/DatabaseMetaDataTest.java b/nitrite/src/test/java/org/dizitart/no2/store/DatabaseMetaDataTest.java deleted file mode 100644 index 963eb1410..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/store/DatabaseMetaDataTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.dizitart.no2.store; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import org.dizitart.no2.collection.Document; -import org.junit.Test; - -public class DatabaseMetaDataTest { - @Test - public void testConstructor() { - DatabaseMetaData actualDatabaseMetaData = new DatabaseMetaData(Document.createDocument()); - assertNull(actualDatabaseMetaData.getStoreVersion()); - assertNull(actualDatabaseMetaData.getSchemaVersion()); - assertNull(actualDatabaseMetaData.getNitriteVersion()); - assertNull(actualDatabaseMetaData.getCreateTime()); - } - - @Test - public void testGetInfo() { - DatabaseMetaData databaseMetaData = new DatabaseMetaData(); - databaseMetaData.setNitriteVersion("1.0.2"); - assertEquals(4, databaseMetaData.getInfo().size()); - } - - @Test - public void testGetInfo2() { - assertEquals(4, (new DatabaseMetaData()).getInfo().size()); - } -} - diff --git a/nitrite/src/test/java/org/dizitart/no2/store/StoreCatalogTest.java b/nitrite/src/test/java/org/dizitart/no2/store/StoreCatalogTest.java new file mode 100644 index 000000000..ded81e974 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/store/StoreCatalogTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.store; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.dizitart.no2.store.memory.InMemoryStore; +import org.junit.Test; + +public class StoreCatalogTest { + @Test + public void testConstructor() { + assertTrue((new StoreCatalog(new InMemoryStore())).getCollectionNames().isEmpty()); + } + + @Test + public void testWriteCollectionEntry() { + StoreCatalog storeCatalog = new StoreCatalog(new InMemoryStore()); + storeCatalog.writeCollectionEntry("Name"); + assertEquals(1, storeCatalog.getCollectionNames().size()); + assertTrue(storeCatalog.getRepositoryNames().isEmpty()); + } + + @Test + public void testWriteRepositoryEntry() { + StoreCatalog storeCatalog = new StoreCatalog(new InMemoryStore()); + storeCatalog.writeRepositoryEntry("Name"); + assertTrue(storeCatalog.getCollectionNames().isEmpty()); + assertEquals(1, storeCatalog.getRepositoryNames().size()); + } + + @Test + public void testWriteKeyedRepositoryEntries() { + StoreCatalog storeCatalog = new StoreCatalog(new InMemoryStore()); + storeCatalog.writeKeyedRepositoryEntries("Name"); + assertTrue(storeCatalog.getCollectionNames().isEmpty()); + } + + @Test + public void testGetCollectionNames() { + assertTrue((new StoreCatalog(new InMemoryStore())).getCollectionNames().isEmpty()); + } + + @Test + public void testGetRepositoryNames() { + assertTrue((new StoreCatalog(new InMemoryStore())).getRepositoryNames().isEmpty()); + } + + @Test + public void testGetKeyedRepositoryNames() { + assertTrue((new StoreCatalog(new InMemoryStore())).getKeyedRepositoryNames().isEmpty()); + } + + @Test + public void testRemove() { + // TODO: This test is incomplete. + // Reason: No meaningful assertions found. + // To help Diffblue Cover to find assertions, please add getters to the + // class under test that return fields written by the method under test. + // See https://diff.blue/R004 + + (new StoreCatalog(new InMemoryStore())).remove("Name"); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/store/StoreMetaDataTest.java b/nitrite/src/test/java/org/dizitart/no2/store/StoreMetaDataTest.java new file mode 100644 index 000000000..0cb5209d5 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/store/StoreMetaDataTest.java @@ -0,0 +1,31 @@ +package org.dizitart.no2.store; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.dizitart.no2.collection.Document; +import org.junit.Test; + +public class StoreMetaDataTest { + @Test + public void testConstructor() { + StoreMetaData actualStoreMetaData = new StoreMetaData(Document.createDocument()); + assertNull(actualStoreMetaData.getStoreVersion()); + assertNull(actualStoreMetaData.getSchemaVersion()); + assertNull(actualStoreMetaData.getNitriteVersion()); + assertNull(actualStoreMetaData.getCreateTime()); + } + + @Test + public void testGetInfo() { + StoreMetaData storeMetaData = new StoreMetaData(); + storeMetaData.setNitriteVersion("1.0.2"); + assertEquals(4, storeMetaData.getInfo().size()); + } + + @Test + public void testGetInfo2() { + assertEquals(4, (new StoreMetaData()).getInfo().size()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/store/UserAuthenticationServiceTest.java b/nitrite/src/test/java/org/dizitart/no2/store/UserAuthenticationServiceTest.java new file mode 100644 index 000000000..aa32c4958 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/store/UserAuthenticationServiceTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.store; + +import org.dizitart.no2.exceptions.NitriteSecurityException; +import org.dizitart.no2.store.memory.InMemoryStore; +import org.junit.Test; + +import static org.junit.Assert.assertThrows; + +public class UserAuthenticationServiceTest { + @Test + public void testConstructor() { + // TODO: This test is incomplete. + // Reason: Nothing to assert: the constructed class does not have observers (e.g. getters or public fields). + // Add observers (e.g. getters or public fields) to the class. + // See https://diff.blue/R002 + + new UserAuthenticationService(null); + } + + @Test + public void testAuthenticate() { + assertThrows(NitriteSecurityException.class, + () -> (new UserAuthenticationService(new InMemoryStore())).authenticate("janedoe", "iloveyou", true)); + } + + @Test + public void testAuthenticate2() { + // TODO: This test is incomplete. + // Reason: No meaningful assertions found. + // To help Diffblue Cover to find assertions, please add getters to the + // class under test that return fields written by the method under test. + // See https://diff.blue/R004 + + (new UserAuthenticationService(new InMemoryStore())).authenticate("", "iloveyou", true); + } + + @Test + public void testAuthenticate3() { + // TODO: This test is incomplete. + // Reason: No meaningful assertions found. + // To help Diffblue Cover to find assertions, please add getters to the + // class under test that return fields written by the method under test. + // See https://diff.blue/R004 + + (new UserAuthenticationService(new InMemoryStore())).authenticate("janedoe", "", true); + } + + @Test + public void testAuthenticate4() { + // TODO: This test is incomplete. + // Reason: No meaningful assertions found. + // To help Diffblue Cover to find assertions, please add getters to the + // class under test that return fields written by the method under test. + // See https://diff.blue/R004 + + (new UserAuthenticationService(new InMemoryStore())).authenticate("janedoe", "iloveyou", false); + } + + @Test + public void testAuthenticate5() { + // TODO: This test is incomplete. + // Reason: No meaningful assertions found. + // To help Diffblue Cover to find assertions, please add getters to the + // class under test that return fields written by the method under test. + // See https://diff.blue/R004 + + (new UserAuthenticationService(new InMemoryStore())).authenticate("", "iloveyou", false); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/store/memory/InMemoryMapTest.java b/nitrite/src/test/java/org/dizitart/no2/store/memory/InMemoryMapTest.java index 70cdf8161..4bf390ec8 100644 --- a/nitrite/src/test/java/org/dizitart/no2/store/memory/InMemoryMapTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/store/memory/InMemoryMapTest.java @@ -1,208 +1,389 @@ package org.dizitart.no2.store.memory; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import org.apache.commons.lang3.mutable.MutableByte; +import org.dizitart.no2.exceptions.ValidationException; import org.junit.Test; +import static org.junit.Assert.*; + public class InMemoryMapTest { - @Test - public void testConstructor() { - InMemoryMap actualInMemoryMap = new InMemoryMap("mapName", null); - assertEquals("mapName", actualInMemoryMap.getName()); - assertEquals(0L, actualInMemoryMap.size()); - assertNull(actualInMemoryMap.getStore()); - } @Test public void testContainsKey() { - InMemoryMap inMemoryMap = new InMemoryMap(null, null); - inMemoryMap.put(null, "value"); - assertFalse(inMemoryMap.containsKey("key")); + assertFalse((new InMemoryMap<>("Map Name", null)).containsKey("Key")); } @Test public void testContainsKey2() { - assertFalse((new InMemoryMap("mapName", null)).containsKey("key")); + InMemoryMap inMemoryMap = new InMemoryMap<>("", null); + inMemoryMap.put("Key", "Value"); + assertTrue(inMemoryMap.containsKey("Key")); } @Test public void testContainsKey3() { - assertFalse((new InMemoryMap("mapName", null)).containsKey(null)); + InMemoryMap inMemoryMap = new InMemoryMap<>("", null); + inMemoryMap.put("Key", "Value"); + inMemoryMap.put("Key", "Value"); + assertTrue(inMemoryMap.containsKey("Key")); } @Test public void testContainsKey4() { - InMemoryMap inMemoryMap = new InMemoryMap(null, null); - inMemoryMap.put("key", "value"); - assertTrue(inMemoryMap.containsKey("key")); + InMemoryMap inMemoryMap = new InMemoryMap<>("", null); + inMemoryMap.put("42", "Value"); + assertFalse(inMemoryMap.containsKey("Key")); } @Test public void testGet() { - assertNull((new InMemoryMap("mapName", null)).get("key")); + assertNull((new InMemoryMap<>("Map Name", null)).get("Key")); } @Test public void testGet2() { - InMemoryMap inMemoryMap = new InMemoryMap(null, null); - inMemoryMap.put("key", "value"); - assertEquals("value", inMemoryMap.get("key")); + InMemoryMap inMemoryMap = new InMemoryMap<>("", null); + inMemoryMap.put("Key", "Value"); + assertEquals("Value", inMemoryMap.get("Key")); + } + + @Test + public void testGet3() { + InMemoryMap inMemoryMap = new InMemoryMap<>("", null); + inMemoryMap.put("42", "Value"); + assertNull(inMemoryMap.get("Key")); + } + + @Test + public void testGet4() { + InMemoryMap inMemoryMap = new InMemoryMap<>("", null); + inMemoryMap.put((byte) 'A', "Value"); + assertNull(inMemoryMap.get((byte) 0)); + } + + @Test + public void testClear() { + InMemoryMap inMemoryMap = new InMemoryMap<>("", null); + inMemoryMap.put("Key", "Value"); + inMemoryMap.clear(); + assertEquals(0L, inMemoryMap.size()); + } + + @Test + public void testClear2() { + InMemoryMap inMemoryMap = new InMemoryMap<>("Map Name", new InMemoryStore()); + inMemoryMap.put("Key", "Value"); + inMemoryMap.clear(); + assertEquals(0L, inMemoryMap.size()); + assertEquals(4, inMemoryMap.getAttributes().getAttributes().size()); + } + + @Test + public void testClear3() { + InMemoryMap inMemoryMap = new InMemoryMap<>("lastModifiedTime", new InMemoryStore()); + inMemoryMap.put("Key", "Value"); + inMemoryMap.clear(); + assertEquals(0L, inMemoryMap.size()); + assertEquals(4, inMemoryMap.getAttributes().getAttributes().size()); + } + + @Test + public void testClear4() { + InMemoryMap inMemoryMap = new InMemoryMap<>("Map Name", new InMemoryStore()); + inMemoryMap.clear(); + assertEquals(0L, inMemoryMap.size()); + assertEquals(4, inMemoryMap.getAttributes().getAttributes().size()); + } + + @Test + public void testClear5() { + InMemoryMap inMemoryMap = new InMemoryMap<>("owner", new InMemoryStore()); + inMemoryMap.clear(); + assertEquals(0L, inMemoryMap.size()); + assertEquals(4, inMemoryMap.getAttributes().getAttributes().size()); } @Test public void testValues() { - assertTrue((new InMemoryMap("mapName", null)).values().isEmpty()); + assertTrue((new InMemoryMap<>("Map Name", null)).values().toList().isEmpty()); } @Test public void testRemove() { - InMemoryMap inMemoryMap = new InMemoryMap("", null); - assertNull(inMemoryMap.remove("key")); + InMemoryMap inMemoryMap = new InMemoryMap<>("", null); + inMemoryMap.put("Key", "Value"); + assertEquals("Value", inMemoryMap.remove("Key")); assertEquals(0L, inMemoryMap.size()); } @Test public void testRemove2() { - InMemoryMap inMemoryMap = new InMemoryMap("", null); - assertNull(inMemoryMap.remove(null)); + InMemoryMap inMemoryMap = new InMemoryMap<>("Map Name", new InMemoryStore()); + inMemoryMap.put("Key", "Value"); + assertEquals("Value", inMemoryMap.remove("Key")); assertEquals(0L, inMemoryMap.size()); + assertEquals(4, inMemoryMap.getAttributes().getAttributes().size()); } @Test public void testRemove3() { - InMemoryMap inMemoryMap = new InMemoryMap("", null); - inMemoryMap.put(new MutableByte(), "value"); - assertNull(inMemoryMap.remove(0)); - assertFalse(inMemoryMap.isEmpty()); + InMemoryMap inMemoryMap = new InMemoryMap<>("", null); + inMemoryMap.put("", "Value"); + assertNull(inMemoryMap.remove("Key")); + assertEquals(1L, inMemoryMap.size()); } @Test - public void testKeySet() { - assertTrue((new InMemoryMap("mapName", null)).keySet().isEmpty()); + public void testRemove4() { + InMemoryMap inMemoryMap = new InMemoryMap<>("Map Name", new InMemoryStore()); + inMemoryMap.put("Key", "Value"); + assertNull(inMemoryMap.remove("42")); + assertEquals(1L, inMemoryMap.size()); + assertEquals(4, inMemoryMap.getAttributes().getAttributes().size()); + } + + @Test + public void testKeys() { + assertTrue((new InMemoryMap<>("Map Name", null)).keys().toList().isEmpty()); } @Test public void testPut() { - InMemoryMap inMemoryMap = new InMemoryMap(null, null); - inMemoryMap.put(null, "value"); + InMemoryMap inMemoryMap = new InMemoryMap<>("", null); + inMemoryMap.put("Key", "Value"); + inMemoryMap.put("Key", "Value"); assertEquals(1L, inMemoryMap.size()); } @Test public void testPut2() { - InMemoryMap inMemoryMap = new InMemoryMap(null, null); - inMemoryMap.put("key", "value"); - assertFalse(inMemoryMap.isEmpty()); + InMemoryMap inMemoryMap = new InMemoryMap<>("Map Name", new InMemoryStore()); + inMemoryMap.put("Key", "Value"); + inMemoryMap.put("Key", "Value"); + assertEquals(1L, inMemoryMap.size()); + assertEquals(4, inMemoryMap.getAttributes().getAttributes().size()); } @Test public void testPut3() { - InMemoryMap inMemoryMap = new InMemoryMap(null, null); - inMemoryMap.put("key", 1); - assertFalse(inMemoryMap.isEmpty()); + InMemoryMap inMemoryMap = new InMemoryMap<>("", null); + inMemoryMap.put("value cannot be null", "Value"); + inMemoryMap.put("Key", "Value"); + assertEquals(2L, inMemoryMap.size()); + } + + @Test(expected = ValidationException.class) + public void testPut4() { + InMemoryMap inMemoryMap = new InMemoryMap<>("", null); + inMemoryMap.put((byte) 'A', "Value"); + inMemoryMap.put("Key", null); + } + + @Test + public void testPut5() { + InMemoryMap inMemoryMap = new InMemoryMap<>("Map Name", new InMemoryStore()); + inMemoryMap.put("42", "Value"); + inMemoryMap.put("Key", "Value"); + assertEquals(2L, inMemoryMap.size()); + assertEquals(4, inMemoryMap.getAttributes().getAttributes().size()); } @Test public void testSize() { - assertEquals(0L, (new InMemoryMap("mapName", null)).size()); + assertEquals(0L, (new InMemoryMap<>("Map Name", null)).size()); } @Test public void testPutIfAbsent() { - InMemoryMap inMemoryMap = new InMemoryMap(null, null); - assertNull(inMemoryMap.putIfAbsent(null, "value")); - assertEquals(1L, inMemoryMap.size()); + InMemoryMap inMemoryMap = new InMemoryMap<>("", null); + inMemoryMap.put("Key", "Value"); + assertEquals("Value", inMemoryMap.putIfAbsent("Key", "Value")); } @Test public void testPutIfAbsent2() { - InMemoryMap inMemoryMap = new InMemoryMap(null, null); - assertNull(inMemoryMap.putIfAbsent("key", "value")); - assertFalse(inMemoryMap.isEmpty()); + InMemoryMap inMemoryMap = new InMemoryMap<>("Map Name", new InMemoryStore()); + inMemoryMap.put("Key", "Value"); + assertEquals("Value", inMemoryMap.putIfAbsent("Key", "Value")); + assertEquals(4, inMemoryMap.getAttributes().getAttributes().size()); + } + + @Test + public void testPutIfAbsent3() { + InMemoryMap inMemoryMap = new InMemoryMap<>("", null); + inMemoryMap.put("value cannot be null", "Value"); + assertNull(inMemoryMap.putIfAbsent("Key", "Value")); + assertEquals(2L, inMemoryMap.size()); + } + + @Test(expected = ValidationException.class) + public void testPutIfAbsent4() { + InMemoryMap inMemoryMap = new InMemoryMap<>("", null); + inMemoryMap.put((byte) 'A', "Value"); + inMemoryMap.putIfAbsent("Key", null); + } + + @Test + public void testPutIfAbsent5() { + InMemoryMap inMemoryMap = new InMemoryMap<>("Map Name", new InMemoryStore()); + inMemoryMap.put("Key", "Value"); + assertNull(inMemoryMap.putIfAbsent("42", "Value")); + assertEquals(2L, inMemoryMap.size()); + assertEquals(4, inMemoryMap.getAttributes().getAttributes().size()); } @Test public void testEntries() { - assertTrue((new InMemoryMap("mapName", null)).entries().isEmpty()); + assertTrue((new InMemoryMap<>("Map Name", null)).entries().toList().isEmpty()); + } + + @Test + public void testReversedEntries() { + assertTrue((new InMemoryMap<>("Map Name", null)).reversedEntries().toList().isEmpty()); } @Test public void testHigherKey() { - assertNull((new InMemoryMap("mapName", null)).higherKey("key")); - assertNull((new InMemoryMap("mapName", null)).higherKey(null)); + assertNull((new InMemoryMap<>("Map Name", null)).higherKey("Key")); + assertNull((new InMemoryMap<>("Map Name", null)).higherKey(null)); } @Test public void testHigherKey2() { - InMemoryMap inMemoryMap = new InMemoryMap(null, null); - inMemoryMap.put("key", "value"); - assertNull(inMemoryMap.higherKey("key")); + InMemoryMap inMemoryMap = new InMemoryMap<>(null, null); + inMemoryMap.put("Key", "Value"); + assertNull(inMemoryMap.higherKey("Key")); + } + + @Test + public void testHigherKey3() { + InMemoryMap inMemoryMap = new InMemoryMap<>(null, null); + inMemoryMap.put((byte) 'A', "Value"); + assertEquals('A', ((Byte) inMemoryMap.higherKey(-1)).byteValue()); } @Test public void testCeilingKey() { - assertNull((new InMemoryMap("mapName", null)).ceilingKey("key")); - assertNull((new InMemoryMap("mapName", null)).ceilingKey(null)); + assertNull((new InMemoryMap<>("Map Name", null)).ceilingKey("Key")); + assertNull((new InMemoryMap<>("Map Name", null)).ceilingKey(null)); } @Test public void testCeilingKey2() { - InMemoryMap inMemoryMap = new InMemoryMap(null, null); - inMemoryMap.put("key", "value"); - assertEquals("key", inMemoryMap.ceilingKey("key")); + InMemoryMap inMemoryMap = new InMemoryMap<>(null, null); + inMemoryMap.put("Key", "Value"); + assertEquals("Key", inMemoryMap.ceilingKey("Key")); } @Test public void testCeilingKey3() { - InMemoryMap inMemoryMap = new InMemoryMap(null, null); - inMemoryMap.put(null, "value"); - assertNull(inMemoryMap.ceilingKey("key")); + InMemoryMap inMemoryMap = new InMemoryMap<>(null, null); + inMemoryMap.put((byte) 'A', "Value"); + assertEquals('A', ((Byte) inMemoryMap.ceilingKey(0)).byteValue()); } @Test public void testLowerKey() { - InMemoryMap inMemoryMap = new InMemoryMap(null, null); - inMemoryMap.put("key", "value"); - assertNull(inMemoryMap.lowerKey("key")); + assertNull((new InMemoryMap<>("Map Name", null)).lowerKey("Key")); + assertNull((new InMemoryMap<>("Map Name", null)).lowerKey(null)); } @Test public void testLowerKey2() { - assertNull((new InMemoryMap("mapName", null)).lowerKey(null)); + InMemoryMap inMemoryMap = new InMemoryMap<>(null, null); + inMemoryMap.put("Key", "Value"); + assertNull(inMemoryMap.lowerKey("Key")); } @Test public void testLowerKey3() { - assertNull((new InMemoryMap("mapName", null)).lowerKey("key")); + InMemoryMap inMemoryMap = new InMemoryMap<>(null, null); + inMemoryMap.put((byte) 'A', "Value"); + assertNull(inMemoryMap.lowerKey(10.0f)); } @Test public void testFloorKey() { - assertNull((new InMemoryMap("mapName", null)).floorKey("key")); - assertNull((new InMemoryMap("mapName", null)).floorKey(null)); + assertNull((new InMemoryMap<>("Map Name", null)).floorKey("Key")); + assertNull((new InMemoryMap<>("Map Name", null)).floorKey(null)); } @Test public void testFloorKey2() { - InMemoryMap inMemoryMap = new InMemoryMap(null, null); - inMemoryMap.put("key", "value"); - assertEquals("key", inMemoryMap.floorKey("key")); + InMemoryMap inMemoryMap = new InMemoryMap<>(null, null); + inMemoryMap.put("Key", "Value"); + assertEquals("Key", inMemoryMap.floorKey("Key")); + } + + @Test + public void testFloorKey3() { + InMemoryMap inMemoryMap = new InMemoryMap<>(null, null); + inMemoryMap.put((byte) 'A', "Value"); + assertNull(inMemoryMap.floorKey(0)); } @Test public void testIsEmpty() { - assertTrue((new InMemoryMap("mapName", null)).isEmpty()); + assertTrue((new InMemoryMap<>("Map Name", null)).isEmpty()); } @Test public void testIsEmpty2() { - InMemoryMap inMemoryMap = new InMemoryMap("", null); - inMemoryMap.put("key", "value"); + InMemoryMap inMemoryMap = new InMemoryMap<>("", null); + inMemoryMap.put("Key", "Value"); assertFalse(inMemoryMap.isEmpty()); } + + @Test + public void testDrop() { + InMemoryMap inMemoryMap = new InMemoryMap<>("Map Name", new InMemoryStore()); + inMemoryMap.put("Key", "Value"); + inMemoryMap.drop(); + assertEquals(0L, inMemoryMap.size()); + assertEquals(4, inMemoryMap.getAttributes().getAttributes().size()); + } + + @Test + public void testDrop2() { + InMemoryMap inMemoryMap = new InMemoryMap<>("42", new InMemoryStore()); + inMemoryMap.put("Key", "Value"); + inMemoryMap.drop(); + assertEquals(0L, inMemoryMap.size()); + assertEquals(4, inMemoryMap.getAttributes().getAttributes().size()); + } + + @Test + public void testDrop3() { + InMemoryMap inMemoryMap = new InMemoryMap<>("Map Name", new InMemoryStore()); + inMemoryMap.drop(); + assertEquals(0L, inMemoryMap.size()); + assertEquals(4, inMemoryMap.getAttributes().getAttributes().size()); + } + + @Test + public void testClose() { + // TODO: This test is incomplete. + // Reason: No meaningful assertions found. + // To help Diffblue Cover to find assertions, please add getters to the + // class under test that return fields written by the method under test. + // See https://diff.blue/R004 + + (new InMemoryMap<>("Map Name", null)).close(); + } + + @Test + public void testConstructor() { + InMemoryMap actualInMemoryMap = new InMemoryMap<>("Map Name", null); + assertEquals("Map Name", actualInMemoryMap.getName()); + assertNull(actualInMemoryMap.getStore()); + } + + @Test + public void testConstructor2() { + InMemoryMap actualInMemoryMap = new InMemoryMap<>("Map Name", null); + assertEquals("Map Name", actualInMemoryMap.getName()); + assertEquals(0L, actualInMemoryMap.size()); + assertNull(actualInMemoryMap.getStore()); + } + } diff --git a/nitrite/src/test/java/org/dizitart/no2/store/memory/InMemoryStoreModuleTest.java b/nitrite/src/test/java/org/dizitart/no2/store/memory/InMemoryStoreModuleTest.java new file mode 100644 index 000000000..13444df87 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/store/memory/InMemoryStoreModuleTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.store.memory; + +import org.dizitart.no2.store.NitriteStore; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class InMemoryStoreModuleTest { + @Test + public void testConstructor() { + NitriteStore store = (new InMemoryStoreModule()).getStore(); + assertTrue(store instanceof InMemoryStore); + assertTrue(((InMemoryConfig) store.getStoreConfig()).eventListeners().isEmpty()); + } + + @Test + public void testWithConfig() { + InMemoryModuleBuilder actualWithConfigResult = InMemoryStoreModule.withConfig(); + assertTrue(actualWithConfigResult.eventListeners().isEmpty()); + assertTrue(actualWithConfigResult.dbConfig().eventListeners().isEmpty()); + } + + @Test + public void testGetStore() { + assertFalse((new InMemoryStoreModule()).getStore().isClosed()); + } + + @Test + public void testPlugins() { + assertEquals(1, (new InMemoryStoreModule()).plugins().size()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/store/memory/InMemoryStoreTest.java b/nitrite/src/test/java/org/dizitart/no2/store/memory/InMemoryStoreTest.java index c64f17656..8b2c7dabf 100644 --- a/nitrite/src/test/java/org/dizitart/no2/store/memory/InMemoryStoreTest.java +++ b/nitrite/src/test/java/org/dizitart/no2/store/memory/InMemoryStoreTest.java @@ -23,7 +23,7 @@ public void testIsReadOnly() { } @Test - public void testClose() { + public void testClose() throws Exception { InMemoryStore inMemoryStore = new InMemoryStore(); inMemoryStore.close(); assertTrue(inMemoryStore.isClosed()); diff --git a/nitrite/src/test/java/org/dizitart/no2/transaction/ChangeTypeTest.java b/nitrite/src/test/java/org/dizitart/no2/transaction/ChangeTypeTest.java new file mode 100644 index 000000000..599c37904 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/transaction/ChangeTypeTest.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.transaction; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class ChangeTypeTest { + + @Test + public void testValueOf3() { + assertEquals(ChangeType.AddProcessor, ChangeType.valueOf("AddProcessor")); + } + + @Test + public void testValues() { + assertEquals(12, ChangeType.values().length); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/transaction/DefaultTransactionalCollectionTest.java b/nitrite/src/test/java/org/dizitart/no2/transaction/DefaultTransactionalCollectionTest.java new file mode 100644 index 000000000..e1c5386ff --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/transaction/DefaultTransactionalCollectionTest.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.transaction; + +import org.dizitart.no2.exceptions.NotIdentifiableException; +import org.dizitart.no2.store.memory.InMemoryStore; +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class DefaultTransactionalCollectionTest { + @Test + public void testConstructor() { + TransactionalConfig transactionalConfig = mock(TransactionalConfig.class); + when(transactionalConfig.getNitriteStore()).thenThrow(new NotIdentifiableException("An error occurred")); + + TransactionContext transactionContext = new TransactionContext(); + transactionContext.setConfig(transactionalConfig); + assertThrows(NotIdentifiableException.class, + () -> new DefaultTransactionalCollection(null, transactionContext, null)); + verify(transactionalConfig).getNitriteStore(); + } + + @Test + public void testConstructor2() { + TransactionalConfig transactionalConfig = mock(TransactionalConfig.class); + TransactionalStore transactionalStore = new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(new InMemoryStore()))); + + doReturn(transactionalStore).when(transactionalConfig).getNitriteStore(); + TransactionContext transactionContext = new TransactionContext(); + transactionContext.setConfig(transactionalConfig); + DefaultTransactionalCollection actualDefaultTransactionalCollection = new DefaultTransactionalCollection(null, + transactionContext, null); + assertNull(actualDefaultTransactionalCollection.getCollectionName()); + assertFalse(actualDefaultTransactionalCollection.isDropped()); + TransactionContext transactionContext1 = actualDefaultTransactionalCollection.getTransactionContext(); + assertSame(transactionContext, transactionContext1); + assertSame(transactionalStore, actualDefaultTransactionalCollection.getStore()); + assertNull(actualDefaultTransactionalCollection.getPrimary()); + assertNull(actualDefaultTransactionalCollection.getNitrite()); + assertNull(actualDefaultTransactionalCollection.getNitriteMap()); + assertNull(actualDefaultTransactionalCollection.getCollectionOperations().getAttributes()); + verify(transactionalConfig, times(2)).getNitriteStore(); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/transaction/DefaultTransactionalRepositoryTest.java b/nitrite/src/test/java/org/dizitart/no2/transaction/DefaultTransactionalRepositoryTest.java new file mode 100644 index 000000000..ad9947681 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/transaction/DefaultTransactionalRepositoryTest.java @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.transaction; + +import org.dizitart.no2.collection.FindOptions; +import org.dizitart.no2.collection.events.CollectionEventListener; +import org.dizitart.no2.collection.meta.Attributes; +import org.dizitart.no2.common.processors.ProcessorChain; +import org.dizitart.no2.filters.Filter; +import org.dizitart.no2.index.IndexOptions; +import org.junit.Test; + +import java.util.ArrayList; + +import static org.mockito.Mockito.*; + +public class DefaultTransactionalRepositoryTest { + @Test + public void testAddProcessor() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + doNothing().when(defaultTransactionalRepository).addProcessor(any()); + defaultTransactionalRepository.addProcessor(new ProcessorChain()); + verify(defaultTransactionalRepository).addProcessor(any()); + } + + @Test + public void testRemoveProcessor() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + doNothing().when(defaultTransactionalRepository) + .removeProcessor(any()); + defaultTransactionalRepository.removeProcessor(new ProcessorChain()); + verify(defaultTransactionalRepository).removeProcessor(any()); + } + + @Test + public void testCreateIndex() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + doNothing().when(defaultTransactionalRepository).createIndex(any(), any()); + defaultTransactionalRepository.createIndex(IndexOptions.indexOptions("Index Type"), "foo", "foo", "foo"); + verify(defaultTransactionalRepository).createIndex(any(), any()); + } + + @Test + public void testRebuildIndex() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + doNothing().when(defaultTransactionalRepository).rebuildIndex(any()); + defaultTransactionalRepository.rebuildIndex("foo", "foo", "foo"); + verify(defaultTransactionalRepository).rebuildIndex(any()); + } + + @Test + public void testListIndices() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + when(defaultTransactionalRepository.listIndices()).thenReturn(new ArrayList<>()); + defaultTransactionalRepository.listIndices(); + verify(defaultTransactionalRepository).listIndices(); + } + + @Test + public void testHasIndex() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + when(defaultTransactionalRepository.hasIndex(any())).thenReturn(true); + defaultTransactionalRepository.hasIndex("foo", "foo", "foo"); + verify(defaultTransactionalRepository).hasIndex(any()); + } + + @Test + public void testIsIndexing() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + when(defaultTransactionalRepository.isIndexing(any())).thenReturn(true); + defaultTransactionalRepository.isIndexing("foo", "foo", "foo"); + verify(defaultTransactionalRepository).isIndexing(any()); + } + + @Test + public void testDropIndex() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + doNothing().when(defaultTransactionalRepository).dropIndex(any()); + defaultTransactionalRepository.dropIndex("foo", "foo", "foo"); + verify(defaultTransactionalRepository).dropIndex(any()); + } + + @Test + public void testDropAllIndices() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + doNothing().when(defaultTransactionalRepository).dropAllIndices(); + defaultTransactionalRepository.dropAllIndices(); + verify(defaultTransactionalRepository).dropAllIndices(); + } + + @Test + public void testInsert() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + when(defaultTransactionalRepository.insert(any())).thenReturn(null); + defaultTransactionalRepository.insert(new Object[]{"42", "42", "42"}); + verify(defaultTransactionalRepository).insert(any()); + } + + @Test + public void testUpdate() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + when(defaultTransactionalRepository.update(any(), anyBoolean())).thenReturn(null); + defaultTransactionalRepository.update("Element", true); + verify(defaultTransactionalRepository).update(any(), anyBoolean()); + } + + @Test + public void testUpdate2() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + when(defaultTransactionalRepository.update(any(), (Object) any(), anyBoolean())).thenReturn(null); + defaultTransactionalRepository.update(mock(Filter.class), "Update", true); + verify(defaultTransactionalRepository).update(any(), (Object) any(), anyBoolean()); + } + + @Test + public void testUpdate3() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + when(defaultTransactionalRepository.update(any(), any(), anyBoolean())).thenReturn(null); + defaultTransactionalRepository.update(mock(Filter.class), null, true); + verify(defaultTransactionalRepository).update(any(), any(), anyBoolean()); + } + + @Test + public void testRemove() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + when(defaultTransactionalRepository.remove((Object) any())).thenReturn(null); + defaultTransactionalRepository.remove("Element"); + verify(defaultTransactionalRepository).remove((Object) any()); + } + + @Test + public void testRemove2() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + when(defaultTransactionalRepository.remove(any(), anyBoolean())).thenReturn(null); + defaultTransactionalRepository.remove(mock(Filter.class), true); + verify(defaultTransactionalRepository).remove(any(), anyBoolean()); + } + + @Test + public void testClear() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + doNothing().when(defaultTransactionalRepository).clear(); + defaultTransactionalRepository.clear(); + verify(defaultTransactionalRepository).clear(); + } + + @Test + public void testFind() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + when(defaultTransactionalRepository.find(any(), any())).thenReturn(null); + Filter filter = mock(Filter.class); + defaultTransactionalRepository.find(filter, new FindOptions()); + verify(defaultTransactionalRepository).find(any(), any()); + } + + @Test + public void testGetById() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + when(defaultTransactionalRepository.getById(any())).thenReturn("42"); + defaultTransactionalRepository.getById("Id"); + verify(defaultTransactionalRepository).getById(any()); + } + + @Test + public void testDrop() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + doNothing().when(defaultTransactionalRepository).drop(); + defaultTransactionalRepository.drop(); + verify(defaultTransactionalRepository).drop(); + } + + @Test + public void testIsDropped() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + when(defaultTransactionalRepository.isDropped()).thenReturn(true); + defaultTransactionalRepository.isDropped(); + verify(defaultTransactionalRepository).isDropped(); + } + + @Test + public void testIsOpen() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + when(defaultTransactionalRepository.isOpen()).thenReturn(true); + defaultTransactionalRepository.isOpen(); + verify(defaultTransactionalRepository).isOpen(); + } + + @Test + public void testClose() throws Exception { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + doNothing().when(defaultTransactionalRepository).close(); + defaultTransactionalRepository.close(); + verify(defaultTransactionalRepository).close(); + } + + @Test + public void testSize() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + when(defaultTransactionalRepository.size()).thenReturn(1L); + defaultTransactionalRepository.size(); + verify(defaultTransactionalRepository).size(); + } + + @Test + public void testGetStore() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + doReturn(new TransactionalStore<>(new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null))))).when(defaultTransactionalRepository).getStore(); + defaultTransactionalRepository.getStore(); + verify(defaultTransactionalRepository).getStore(); + } + + @Test + public void testSubscribe() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + doNothing().when(defaultTransactionalRepository).subscribe(any()); + defaultTransactionalRepository.subscribe(mock(CollectionEventListener.class)); + verify(defaultTransactionalRepository).subscribe(any()); + } + + @Test + public void testUnsubscribe() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + doNothing().when(defaultTransactionalRepository).unsubscribe(any()); + defaultTransactionalRepository.unsubscribe(mock(CollectionEventListener.class)); + verify(defaultTransactionalRepository).unsubscribe(any()); + } + + @Test + public void testGetAttributes() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + when(defaultTransactionalRepository.getAttributes()).thenReturn(new Attributes()); + defaultTransactionalRepository.getAttributes(); + verify(defaultTransactionalRepository).getAttributes(); + } + + @Test + public void testSetAttributes() { + DefaultTransactionalRepository defaultTransactionalRepository = (DefaultTransactionalRepository) mock( + DefaultTransactionalRepository.class); + doNothing().when(defaultTransactionalRepository).setAttributes(any()); + defaultTransactionalRepository.setAttributes(new Attributes()); + verify(defaultTransactionalRepository).setAttributes(any()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/transaction/JournalEntryTest.java b/nitrite/src/test/java/org/dizitart/no2/transaction/JournalEntryTest.java new file mode 100644 index 000000000..831a9e6dc --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/transaction/JournalEntryTest.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.transaction; + +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; + +public class JournalEntryTest { + @Test + public void testCanEqual() { + assertFalse((new JournalEntry()).canEqual("Other")); + } + + @Test + public void testCanEqual2() { + JournalEntry journalEntry = new JournalEntry(); + assertTrue(journalEntry.canEqual(new JournalEntry())); + } + + @Test + public void testConstructor() { + JournalEntry actualJournalEntry = new JournalEntry(); + actualJournalEntry.setChangeType(ChangeType.Insert); + actualJournalEntry.setCommit(mock(Command.class)); + actualJournalEntry.setRollback(mock(Command.class)); + assertEquals(ChangeType.Insert, actualJournalEntry.getChangeType()); + } + + @Test + public void testConstructor2() { + JournalEntry actualJournalEntry = new JournalEntry(ChangeType.Insert, mock(Command.class), mock(Command.class)); + actualJournalEntry.setChangeType(ChangeType.Insert); + actualJournalEntry.setCommit(mock(Command.class)); + actualJournalEntry.setRollback(mock(Command.class)); + assertEquals(ChangeType.Insert, actualJournalEntry.getChangeType()); + } + + @Test + public void testEquals() { + assertFalse((new JournalEntry()).equals("42")); + } + + @Test + public void testEquals2() { + JournalEntry journalEntry = new JournalEntry(); + assertTrue(journalEntry.equals(new JournalEntry())); + } + + @Test + public void testEquals3() { + JournalEntry journalEntry = new JournalEntry(); + assertFalse(journalEntry.equals(new JournalEntry(ChangeType.Insert, mock(Command.class), mock(Command.class)))); + } + + @Test + public void testEquals4() { + JournalEntry journalEntry = new JournalEntry(ChangeType.Insert, mock(Command.class), mock(Command.class)); + assertFalse(journalEntry.equals(new JournalEntry())); + } + + @Test + public void testEquals5() { + JournalEntry journalEntry = new JournalEntry(ChangeType.Insert, mock(Command.class), mock(Command.class)); + assertFalse(journalEntry.equals(new JournalEntry(ChangeType.Insert, mock(Command.class), mock(Command.class)))); + } + + @Test + public void testEquals6() { + JournalEntry journalEntry = new JournalEntry(); + assertFalse(journalEntry.equals(new JournalEntry(null, mock(Command.class), mock(Command.class)))); + } + + @Test + public void testEquals7() { + JournalEntry journalEntry = new JournalEntry(); + journalEntry.setRollback(mock(Command.class)); + assertFalse(journalEntry.equals(new JournalEntry())); + } + + @Test + public void testEquals8() { + JournalEntry journalEntry = new JournalEntry(); + + JournalEntry journalEntry1 = new JournalEntry(); + journalEntry1.setRollback(mock(Command.class)); + assertFalse(journalEntry.equals(journalEntry1)); + } + + @Test + public void testHashCode() { + assertEquals(357642, (new JournalEntry()).hashCode()); + } + + @Test + public void testHashCode2() { + // TODO: This test is incomplete. + // Reason: No meaningful assertions found. + // To help Diffblue Cover to find assertions, please add getters to the + // class under test that return fields written by the method under test. + // See https://diff.blue/R004 + + (new JournalEntry(ChangeType.Insert, mock(Command.class), mock(Command.class))).hashCode(); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/transaction/NitriteTransactionTest.java b/nitrite/src/test/java/org/dizitart/no2/transaction/NitriteTransactionTest.java new file mode 100644 index 000000000..79e36d5f9 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/transaction/NitriteTransactionTest.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.transaction; + +import org.dizitart.no2.Nitrite; +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.common.concurrent.LockService; +import org.dizitart.no2.store.memory.InMemoryStore; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; + +public class NitriteTransactionTest { + @Test + public void testConstructor() { + Nitrite nitrite = mock(Nitrite.class); + when(nitrite.getConfig()).thenReturn(new NitriteConfig()); + doReturn(new TransactionalStore<>(new InMemoryStore())).when(nitrite).getStore(); + assertEquals(State.Active, (new NitriteTransaction(nitrite, new LockService())).getState()); + verify(nitrite).getConfig(); + verify(nitrite).getStore(); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/transaction/StateTest.java b/nitrite/src/test/java/org/dizitart/no2/transaction/StateTest.java new file mode 100644 index 000000000..ba93373cc --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/transaction/StateTest.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.transaction; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class StateTest { + @Test + public void testValueOf2() { + assertEquals(State.Aborted, State.valueOf("Aborted")); + } + + @Test + public void testValues() { + State[] actualValuesResult = State.values(); + assertEquals(6, actualValuesResult.length); + assertEquals(State.Active, actualValuesResult[0]); + assertEquals(State.PartiallyCommitted, actualValuesResult[1]); + assertEquals(State.Committed, actualValuesResult[2]); + assertEquals(State.Closed, actualValuesResult[3]); + assertEquals(State.Failed, actualValuesResult[4]); + assertEquals(State.Aborted, actualValuesResult[5]); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionCollectionTest.java b/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionCollectionTest.java deleted file mode 100644 index a235b8dfd..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionCollectionTest.java +++ /dev/null @@ -1,770 +0,0 @@ -package org.dizitart.no2.transaction; - -import com.github.javafaker.Faker; -import org.dizitart.no2.collection.BaseCollectionTest; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.TransactionException; -import org.dizitart.no2.index.IndexType; -import org.junit.Test; - -import java.util.*; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.collection.UpdateOptions.updateOptions; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -public class TransactionCollectionTest extends BaseCollectionTest { - - @Test - public void testCommitInsert() { - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - - Document document = createDocument("firstName", "John"); - txCol.insert(document); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); - assertNotEquals(collection.find(where("firstName").eq("John")).size(), 1); - - transaction.commit(); - - assertEquals(collection.find(where("firstName").eq("John")).size(), 1); - } - } - } - - @Test - public void testRollbackInsert() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - NitriteCollection txCol = transaction.getCollection("test"); - - Document document = createDocument("firstName", "John"); - Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); - txCol.insert(document); - txCol.insert(document2); - - // just to create UniqueConstraintViolation for rollback - collection.insert(createDocument("firstName", "Jane")); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertNotEquals(collection.find(where("firstName").eq("John")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - } - } - } - - @Test - public void testCommitUpdate() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - document.put("lastName", "Doe"); - - txCol.update(where("firstName").eq("John"), document, updateOptions(true)); - - assertEquals(txCol.find(where("lastName").eq("Doe")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - - transaction.commit(); - - assertEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - } - } - } - - @Test - public void testRollbackUpdate() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.insert(createDocument("firstName", "Jane")); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - NitriteCollection txCol = transaction.getCollection("test"); - - Document document = createDocument("firstName", "John"); - Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); - txCol.update(where("firstName").eq("Jane"), document2); - txCol.insert(document); - - // just to create UniqueConstraintViolation for rollback - collection.insert(createDocument("firstName", "John")); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); - assertEquals(txCol.find(where("lastName").eq("Doe")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(collection.find(where("firstName").eq("Jane")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - } - } - } - - @Test - public void testCommitRemove() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - - txCol.remove(where("firstName").eq("John")); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 0); - assertEquals(collection.find(where("firstName").eq("John")).size(), 1); - - transaction.commit(); - - assertEquals(collection.find(where("firstName").eq("John")).size(), 0); - } - } - } - - @Test - public void testRollbackRemove() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - - txCol.remove(where("firstName").eq("John")); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 0); - assertEquals(collection.find(where("firstName").eq("John")).size(), 1); - - txCol.insert(createDocument("firstName", "Jane")); - collection.insert(createDocument("firstName", "Jane")); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(collection.find(where("firstName").eq("John")).size(), 1); - assertEquals(collection.find(where("firstName").eq("Jane")).size(), 1); - } - } - } - - @Test - public void testCommitCreateIndex() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - txCol.createIndex("firstName", indexOptions(IndexType.Fulltext)); - - assertTrue(txCol.hasIndex("firstName")); - assertFalse(collection.hasIndex("firstName")); - - transaction.commit(); - - assertTrue(collection.hasIndex("firstName")); - } - } - } - - @Test - public void testRollbackCreateIndex() { - Document document = createDocument("firstName", "John"); - Document document2 = createDocument("firstName", "Jane"); - collection.insert(document); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - - txCol.createIndex("firstName", indexOptions(IndexType.Unique)); - - assertTrue(txCol.hasIndex("firstName")); - assertFalse(collection.hasIndex("firstName")); - - txCol.insert(document2); - collection.insert(document2); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertFalse(collection.hasIndex("firstName")); - } - } - } - - @Test - public void testCommitClear() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - txCol.clear(); - - assertEquals(0, txCol.size()); - assertEquals(1, collection.size()); - - transaction.commit(); - - assertEquals(0, collection.size()); - } - } - } - - @Test - public void testRollbackClear() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - Document document = createDocument("firstName", "John"); - Document document2 = createDocument("firstName", "Jane"); - collection.insert(document); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - - txCol.clear(); - - assertEquals(0, txCol.size()); - assertEquals(1, collection.size()); - - txCol.insert(document2); - collection.insert(document2); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(2, collection.size()); - } - } - } - - @Test - public void testCommitDropIndex() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - txCol.dropIndex("firstName"); - - assertFalse(txCol.hasIndex("firstName")); - assertTrue(collection.hasIndex("firstName")); - - transaction.commit(); - - assertFalse(collection.hasIndex("firstName")); - } - } - } - - @Test - public void testRollbackDropIndex() { - Document document = createDocument("firstName", "John").put("lastName", "Doe"); - Document document2 = createDocument("firstName", "Jane").put("lastName", "Doe"); - collection.insert(document); - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - txCol.dropIndex("lastName"); - - assertFalse(txCol.hasIndex("lastName")); - assertTrue(collection.hasIndex("lastName")); - - txCol.insert(document2); - collection.insert(document2); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertTrue(collection.hasIndex("lastName")); - } - } - } - - @Test - public void testCommitDropAllIndices() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("lastName", indexOptions(IndexType.Unique)); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - txCol.dropAllIndices(); - - assertFalse(txCol.hasIndex("firstName")); - assertFalse(txCol.hasIndex("lastName")); - assertTrue(collection.hasIndex("firstName")); - assertTrue(collection.hasIndex("lastName")); - - transaction.commit(); - - assertFalse(collection.hasIndex("firstName")); - assertFalse(collection.hasIndex("lastName")); - } - } - } - - @Test - public void testRollbackDropAllIndices() { - Document document = createDocument("firstName", "John").put("lastName", "Doe"); - collection.insert(document); - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - collection.createIndex("lastName", indexOptions(IndexType.NonUnique)); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - txCol.dropAllIndices(); - - assertFalse(txCol.hasIndex("firstName")); - assertFalse(txCol.hasIndex("lastName")); - assertTrue(collection.hasIndex("firstName")); - assertTrue(collection.hasIndex("lastName")); - - txCol.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); - collection.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertTrue(collection.hasIndex("firstName")); - assertTrue(collection.hasIndex("lastName")); - } - } - } - - @Test - public void testCommitDropCollection() { - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - txCol.drop(); - - boolean expectedException = false; - try { - assertEquals(0, txCol.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - assertEquals(1, collection.size()); - - transaction.commit(); - - expectedException = false; - try { - assertEquals(0, collection.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - } - } - } - - @Test - public void testRollbackDropCollection() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - Document document = createDocument("firstName", "John"); - collection.insert(document); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - NitriteCollection txCol = transaction.getCollection("test"); - - txCol.drop(); - - boolean expectedException = false; - try { - assertEquals(0, txCol.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - assertEquals(1, collection.size()); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(1, collection.size()); - } - } - } - - @Test - public void testCommitSetAttribute() { - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - NitriteCollection txCol = transaction.getCollection("test"); - - Attributes attributes = new Attributes(); - attributes.setAttributes(Collections.singletonMap("key", "value")); - txCol.setAttributes(attributes); - - assertNull(collection.getAttributes()); - - transaction.commit(); - - assertEquals("value", collection.getAttributes().get("key")); - } - } - } - - @Test - public void testRollbackSetAttribute() { - collection.createIndex("firstName", indexOptions(IndexType.Unique)); - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - NitriteCollection txCol = transaction.getCollection("test"); - - Attributes attributes = new Attributes(); - Map map = new HashMap<>(); - map.put("key", "value"); - attributes.setAttributes(map); - txCol.setAttributes(attributes); - - txCol.insert(createDocument("firstName", "John")); - txCol.insert(createDocument("firstName", "Jane").put("lastName", "Doe")); - - assertNull(collection.getAttributes()); - - // just to create UniqueConstraintViolation for rollback - collection.insert(createDocument("firstName", "Jane")); - - assertEquals(txCol.find(where("firstName").eq("John")).size(), 1); - assertNotEquals(collection.find(where("lastName").eq("Doe")).size(), 1); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertNull(collection.getAttributes().get("key")); - } - } - } - - @Test - public void testConcurrentInsertAndRemove() { - NitriteCollection collection = db.getCollection("test"); - collection.createIndex("firstName", indexOptions(IndexType.NonUnique)); - collection.createIndex("id", indexOptions(IndexType.Unique)); - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - final long fi = i; - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - NitriteCollection txCol = transaction.getCollection("test"); - - for (int j = 0; j < 10; j++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("lastName", faker.name().lastName()) - .put("id", j + (fi * 10)); - txCol.insert(document); - } - - txCol.remove(where("id").eq(2 + (fi * 10))); - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(90, collection.size()); - } - } - - @Test - public void testConcurrentInsert() { - NitriteCollection collection = db.getCollection("test"); - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - NitriteCollection txCol = transaction.getCollection("test"); - - for (int j = 0; j < 10; j++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("lastName", faker.name().lastName()); - txCol.insert(document); - } - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(100, collection.size()); - } - } - - @Test - public void testConcurrentUpdate() { - NitriteCollection collection = db.getCollection("test"); - for (int i = 0; i < 10; i++) { - Document document = createDocument("id", i); - collection.insert(document); - } - - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - NitriteCollection txCol = transaction.getCollection("test"); - - for (int j = 0; j < 10; j++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("lastName", faker.name().lastName()) - .put("id", j); - txCol.update(where("id").eq(j), document, updateOptions(true)); - } - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(10, collection.size()); - } - } - - @Test - public void testTransactionOnDifferentCollections() { - NitriteCollection col1 = db.getCollection("test1"); - NitriteCollection col2 = db.getCollection("test2"); - NitriteCollection col3 = db.getCollection("test3"); - col3.createIndex("id", indexOptions(IndexType.Unique)); - - Faker faker = new Faker(); - - try(Session session = db.createSession()) { - Transaction transaction = session.beginTransaction(); - - NitriteCollection test1 = transaction.getCollection("test1"); - NitriteCollection test2 = transaction.getCollection("test2"); - NitriteCollection test3 = transaction.getCollection("test3"); - - for (int i = 0; i < 10; i++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", i); - test1.insert(document); - - document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 10); - test2.insert(document); - - document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 20); - test3.insert(document); - } - - assertEquals(test1.size(), 10); - assertEquals(test2.size(), 10); - assertEquals(test3.size(), 10); - - assertEquals(col1.size(), 0); - assertEquals(col2.size(), 0); - assertEquals(col3.size(), 0); - - transaction.commit(); - - assertEquals(col1.size(), 10); - assertEquals(col2.size(), 10); - assertEquals(col3.size(), 10); - } - - - Transaction transaction = null; - try (Session session = db.createSession()) { - transaction = session.beginTransaction(); - - NitriteCollection test1 = transaction.getCollection("test1"); - NitriteCollection test2 = transaction.getCollection("test2"); - NitriteCollection test3 = transaction.getCollection("test3"); - - for (int i = 0; i < 10; i++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 30); - test1.insert(document); - - document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 40); - test2.insert(document); - - document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 50); - test3.insert(document); - } - - assertEquals(test1.size(), 20); - assertEquals(test2.size(), 20); - assertEquals(test3.size(), 20); - - assertEquals(col1.size(), 10); - assertEquals(col2.size(), 10); - assertEquals(col3.size(), 10); - - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", 52); - col3.insert(document); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - - assertEquals(col1.size(), 10); - assertEquals(col2.size(), 10); - assertEquals(col3.size(), 11); // last document added - } - } - - @Test(expected = TransactionException.class) - public void testFailureOnClosedTransaction() { - try(Session session = db.createSession()) { - Transaction transaction = session.beginTransaction(); - NitriteCollection col = transaction.getCollection("test"); - col.insert(createDocument("id", 1)); - transaction.commit(); - - col.insert(createDocument("id", 2)); - fail(); - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionContextTest.java b/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionContextTest.java new file mode 100644 index 000000000..d5a12e2b6 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionContextTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.transaction; + +import org.dizitart.no2.collection.Document; +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.store.NitriteMap; +import org.dizitart.no2.store.memory.InMemoryStore; +import org.junit.Test; + +import java.util.LinkedList; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class TransactionContextTest { + @Test + public void testConstructor() { + assertEquals("TransactionContext(collectionName=null, journal=null, nitriteMap=null, config=null, active=true)", + (new TransactionContext()).toString()); + } + + @Test + public void testClose() throws Exception { + LinkedList journalEntryList = new LinkedList<>(); + journalEntryList.add(new JournalEntry()); + + TransactionContext transactionContext = new TransactionContext(); + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + transactionContext + .setNitriteMap(new TransactionalMap<>("Map Name", primary2, new InMemoryStore())); + transactionContext.setJournal(journalEntryList); + transactionContext.close(); + assertTrue(transactionContext.getJournal().isEmpty()); + NitriteMap nitriteMap = transactionContext.getNitriteMap(); + assertEquals(0L, nitriteMap.size()); + assertTrue(nitriteMap.entries().toList().isEmpty()); + assertEquals(4, nitriteMap.getAttributes().getAttributes().size()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionRepositoryTest.java b/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionRepositoryTest.java deleted file mode 100644 index b5b947381..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionRepositoryTest.java +++ /dev/null @@ -1,808 +0,0 @@ -package org.dizitart.no2.transaction; - -import com.github.javafaker.Faker; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.collection.NitriteCollection; -import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.exceptions.NitriteIOException; -import org.dizitart.no2.exceptions.TransactionException; -import org.dizitart.no2.index.IndexType; -import org.dizitart.no2.repository.BaseObjectRepositoryTest; -import org.dizitart.no2.repository.ObjectRepository; -import org.dizitart.no2.repository.data.SubEmployee; -import org.junit.Test; - -import java.util.*; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -import static org.dizitart.no2.collection.Document.createDocument; -import static org.dizitart.no2.filters.FluentFilter.where; -import static org.dizitart.no2.index.IndexOptions.indexOptions; -import static org.junit.Assert.*; - -/** - * @author Anindya Chatterjee - */ -public class TransactionRepositoryTest extends BaseObjectRepositoryTest { - - @Test - public void testCommitInsert() { - ObjectRepository repository = db.getRepository(TxData.class); - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - TxData txData1 = new TxData(); - txData1.setId(1L); - txData1.setName("John"); - - txRepo.insert(txData1); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 1); - assertNotEquals(repository.find(where("name").eq("John")).size(), 1); - - transaction.commit(); - - assertEquals(repository.find(where("name").eq("John")).size(), 1); - } - } - } - - @Test - public void testRollbackInsert() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - TxData txData1 = new TxData(); - txData1.setId(1L); - txData1.setName("John"); - - TxData txData2 = new TxData(); - txData2.setId(2L); - txData2.setName("Jane"); - - txRepo.insert(txData1, txData2); - - txData2.setName("Molly"); - repository.insert(txData2); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 1); - assertEquals(repository.find(where("name").eq("John")).size(), 0); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(repository.find(where("name").eq("John")).size(), 0); - assertEquals(repository.find(where("name").eq("Molly")).size(), 1); - } - } - } - - @Test - public void testCommitUpdate() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(new TxData(1L, "John")); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - TxData txData1 = new TxData(1L, "Jane"); - txRepo.update(txData1, true); - - assertEquals(txRepo.find(where("name").eq("Jane")).size(), 1); - assertNotEquals(repository.find(where("name").eq("Jane")).size(), 1); - - transaction.commit(); - - assertEquals(repository.find(where("name").eq("Jane")).size(), 1); - } - } - } - - @Test - public void testRollbackUpdate() { - ObjectRepository repository = db.getRepository(TxData.class, "rollback"); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(new TxData(1L, "Jane")); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - ObjectRepository txRepo = transaction.getRepository(TxData.class, "rollback"); - - TxData txData1 = new TxData(); - txData1.setId(2L); - txData1.setName("John"); - - TxData txData2 = new TxData(); - txData2.setId(1L); - txData2.setName("Jane Doe"); - txRepo.update(txData2); - txRepo.insert(txData1); - - // just to create UniqueConstraintViolation for rollback - repository.insert(txData1); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 1); - assertEquals(txRepo.find(where("name").eq("Jane Doe")).size(), 1); - assertNotEquals(repository.find(where("name").eq("Jane Doe")).size(), 1); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(repository.find(where("name").eq("Jane")).size(), 1); - assertNotEquals(repository.find(where("name").eq("Jane Doe")).size(), 1); - } - } - } - - @Test - public void testCommitRemove() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - txRepo.remove(where("name").eq("John")); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 0); - assertEquals(repository.find(where("name").eq("John")).size(), 1); - - transaction.commit(); - - assertEquals(repository.find(where("name").eq("John")).size(), 0); - } - } - } - - @Test - public void testRollbackRemove() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - TxData txData1 = new TxData(1L, "John"); - repository.insert(txData1); - - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - txRepo.remove(where("name").eq("John")); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 0); - assertEquals(repository.find(where("name").eq("John")).size(), 1); - - TxData txData2 = new TxData(2L, "Jane"); - txRepo.insert(txData2); - repository.insert(txData2); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(repository.find(where("name").eq("John")).size(), 1); - assertEquals(repository.find(where("name").eq("Jane")).size(), 1); - } - } - } - - @Test - public void testCommitCreateIndex() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.createIndex("name", indexOptions(IndexType.Fulltext)); - - assertTrue(txRepo.hasIndex("name")); - assertFalse(repository.hasIndex("name")); - - transaction.commit(); - - assertTrue(repository.hasIndex("name")); - } - } - } - - @Test - public void testRollbackCreateIndex() { - TxData txData1 = new TxData(1L, "John"); - TxData txData2 = new TxData(2L, "Jane"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.createIndex("name", indexOptions(IndexType.Fulltext)); - - assertTrue(txRepo.hasIndex("name")); - assertFalse(repository.hasIndex("name")); - - txRepo.insert(txData2); - repository.insert(txData2); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertFalse(repository.hasIndex("name")); - } - } - } - - @Test - public void testCommitClear() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.clear(); - - assertEquals(0, txRepo.size()); - assertEquals(1, repository.size()); - - transaction.commit(); - - assertEquals(0, repository.size()); - } - } - } - - @Test - public void testRollbackClear() { - TxData txData1 = new TxData(1L, "John"); - TxData txData2 = new TxData(2L, "Jane"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.clear(); - - assertEquals(0, txRepo.size()); - assertEquals(1, repository.size()); - - txRepo.insert(txData2); - repository.insert(txData2); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(2, repository.size()); - } - } - } - - @Test - public void testCommitDropIndex() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.dropIndex("name"); - - assertFalse(txRepo.hasIndex("name")); - assertTrue(repository.hasIndex("name")); - - transaction.commit(); - - assertFalse(repository.hasIndex("name")); - } - } - } - - @Test - public void testRollbackDropIndex() { - TxData txData1 = new TxData(1L, "John"); - TxData txData2 = new TxData(2L, "Jane"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.dropIndex("name"); - - assertFalse(txRepo.hasIndex("name")); - assertTrue(repository.hasIndex("name")); - - txRepo.insert(txData2); - repository.insert(txData2); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertTrue(repository.hasIndex("name")); - } - } - } - - @Test - public void testCommitDropAllIndices() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.dropAllIndices(); - - assertFalse(txRepo.hasIndex("name")); - assertTrue(repository.hasIndex("name")); - - transaction.commit(); - - assertFalse(repository.hasIndex("name")); - } - } - } - - @Test - public void testRollbackDropAllIndices() { - TxData txData1 = new TxData(1L, "John"); - TxData txData2 = new TxData(2L, "Jane"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.dropAllIndices(); - - assertFalse(txRepo.hasIndex("name")); - assertTrue(repository.hasIndex("name")); - - txRepo.insert(txData2); - repository.insert(txData2); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertTrue(repository.hasIndex("name")); - } - } - } - - @Test - public void testCommitDropRepository() { - TxData txData1 = new TxData(1L, "John"); - ObjectRepository repository = db.getRepository(TxData.class); - repository.insert(txData1); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.drop(); - - boolean expectedException = false; - try { - assertEquals(0, txRepo.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - assertEquals(1, repository.size()); - - transaction.commit(); - - expectedException = false; - try { - assertEquals(0, repository.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - } - } - } - - @Test - public void testRollbackDropRepository() { - TxData txData1 = new TxData(1L, "John"); - - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - repository.insert(txData1); - - try(Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.drop(); - - boolean expectedException = false; - try { - assertEquals(0, txRepo.size()); - } catch (NitriteIOException e) { - expectedException = true; - } - assertTrue(expectedException); - assertEquals(1, repository.size()); - - throw new TransactionException("failed"); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertEquals(1, repository.size()); - } - } - } - - @Test - public void testCommitSetAttribute() { - ObjectRepository repository = db.getRepository(TxData.class); - - try (Session session = db.createSession()) { - try (Transaction transaction = session.beginTransaction()) { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - Attributes attributes = new Attributes(); - attributes.setAttributes(Collections.singletonMap("key", "value")); - txRepo.setAttributes(attributes); - - assertNull(repository.getAttributes()); - - transaction.commit(); - - assertEquals("value", repository.getAttributes().get("key")); - } - } - } - - @Test - public void testRollbackSetAttribute() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.Unique)); - try (Session session = db.createSession()) { - Transaction transaction = null; - try { - transaction = session.beginTransaction(); - - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - Attributes attributes = new Attributes(); - Map map = new HashMap<>(); - map.put("key", "value"); - attributes.setAttributes(map); - txRepo.setAttributes(attributes); - - txRepo.insert(new TxData(1L, "John")); - txRepo.insert(new TxData(2L, "Jane")); - - assertNull(repository.getAttributes()); - - // just to create UniqueConstraintViolation for rollback - repository.insert(new TxData(2L, "Jane")); - - assertEquals(txRepo.find(where("name").eq("John")).size(), 1); - assertNotEquals(repository.find(where("name").eq("John")).size(), 1); - - transaction.commit(); - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - assertNull(repository.getAttributes().get("key")); - } - } - } - - @Test - public void testConcurrentInsertAndRemove() { - ObjectRepository repository = db.getRepository(TxData.class); - repository.createIndex("name", indexOptions(IndexType.NonUnique)); - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - final long fi = i; - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - for (long j = 0; j < 10; j++) { - TxData txData = new TxData(j + (fi * 10), faker.name().name()); - txRepo.insert(txData); - } - - txRepo.remove(where("id").eq(2L + (fi * 10))); - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(90, repository.size()); - } - } - - @Test - public void testConcurrentInsert() { - ObjectRepository repository = db.getRepository(TxData.class); - Faker faker = new Faker(); - List> futures = new ArrayList<>(); - - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - final long fi = i; - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - for (long j = 0; j < 10; j++) { - TxData txData = new TxData(j + (fi * 10), faker.name().name()); - txRepo.insert(txData); - } - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(100, repository.size()); - } - } - - @Test - public void testConcurrentUpdate() { - ObjectRepository repository = db.getRepository(TxData.class); - Faker faker = new Faker(); - for (long j = 0; j < 10; j++) { - TxData txData = new TxData(j, faker.name().name()); - repository.insert(txData); - } - - List> futures = new ArrayList<>(); - try (Session session = db.createSession()) { - ExecutorService executorService = Executors.newCachedThreadPool(); - for (int i = 0; i < 10; i++) { - Future future = executorService.submit(() -> { - Transaction transaction = session.beginTransaction(); - try { - ObjectRepository txRepo = transaction.getRepository(TxData.class); - - for (int j = 0; j < 10; j++) { - TxData txData = new TxData((long) j, faker.name().name()); - txRepo.update(where("id").eq(j), txData); - } - - transaction.commit(); - } catch (Exception e) { - e.printStackTrace(); - transaction.rollback(); - } finally { - transaction.close(); - } - }); - - futures.add(future); - } - - futures.forEach(future -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); - - assertEquals(10, repository.size()); - } - } - - @Test - public void testTransactionOnDifferentRepositoriesAndCollections() { - ObjectRepository repo1 = db.getRepository(TxData.class); - ObjectRepository repo2 = db.getRepository(TxData.class, "2"); - ObjectRepository repo3 = db.getRepository(SubEmployee.class); - NitriteCollection col1 = db.getCollection("test1"); - col1.createIndex("id", indexOptions(IndexType.Unique)); - - Faker faker = new Faker(); - - try(Session session = db.createSession()) { - Transaction transaction = session.beginTransaction(); - - ObjectRepository txRepo1 = transaction.getRepository(TxData.class); - ObjectRepository txRepo2 = transaction.getRepository(TxData.class, "2"); - ObjectRepository txRepo3 = transaction.getRepository(SubEmployee.class); - NitriteCollection test1 = transaction.getCollection("test1"); - - for (long i = 0; i < 10; i++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", i); - test1.insert(document); - - TxData txData1 = new TxData(i, faker.name().name()); - txRepo1.insert(txData1); - - TxData txData2 = new TxData(i + 10, faker.name().name()); - txRepo2.insert(txData2); - - SubEmployee employee = new SubEmployee(); - employee.setAddress(faker.address().fullAddress()); - employee.setEmpId(i); - employee.setJoinDate(faker.date().birthday()); - txRepo3.insert(employee); - } - - assertEquals(test1.size(), 10); - assertEquals(txRepo1.size(), 10); - assertEquals(txRepo2.size(), 10); - assertEquals(txRepo3.size(), 10); - - assertEquals(col1.size(), 0); - assertEquals(repo1.size(), 0); - assertEquals(repo2.size(), 0); - assertEquals(repo3.size(), 0); - - transaction.commit(); - - assertEquals(col1.size(), 10); - assertEquals(repo1.size(), 10); - assertEquals(repo2.size(), 10); - assertEquals(repo3.size(), 10); - } - - Transaction transaction = null; - try (Session session = db.createSession()) { - transaction = session.beginTransaction(); - - ObjectRepository txRepo1 = transaction.getRepository(TxData.class); - ObjectRepository txRepo2 = transaction.getRepository(TxData.class, "2"); - ObjectRepository txRepo3 = transaction.getRepository(SubEmployee.class); - NitriteCollection test1 = transaction.getCollection("test1"); - - for (long i = 0; i < 10; i++) { - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", i + 10); - test1.insert(document); - - TxData txData1 = new TxData(i + 10, faker.name().name()); - txRepo1.insert(txData1); - - TxData txData2 = new TxData(i + 20, faker.name().name()); - txRepo2.insert(txData2); - - SubEmployee employee = new SubEmployee(); - employee.setAddress(faker.address().fullAddress()); - employee.setEmpId(i + 10); - employee.setJoinDate(faker.date().birthday()); - txRepo3.insert(employee); - } - - assertEquals(test1.size(), 20); - assertEquals(txRepo1.size(), 20); - assertEquals(txRepo2.size(), 20); - assertEquals(txRepo3.size(), 20); - - assertEquals(col1.size(), 10); - assertEquals(repo1.size(), 10); - assertEquals(repo2.size(), 10); - assertEquals(repo3.size(), 10); - - Document document = createDocument("firstName", faker.name().firstName()) - .put("id", 12L); - col1.insert(document); - - transaction.commit(); - - fail(); - } catch (TransactionException e) { - assert transaction != null; - transaction.rollback(); - - assertEquals(col1.size(), 11); // last doc added - assertEquals(repo1.size(), 10); - assertEquals(repo2.size(), 10); - assertEquals(repo3.size(), 10); - } - } - - @Test(expected = TransactionException.class) - public void testFailureOnClosedTransaction() { - try(Session session = db.createSession()) { - Transaction transaction = session.beginTransaction(); - ObjectRepository txRepo = transaction.getRepository(TxData.class); - txRepo.insert(new TxData(1L, "John")); - transaction.commit(); - - txRepo.insert(new TxData(2L, "Jane")); - fail(); - } - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionalConfigTest.java b/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionalConfigTest.java new file mode 100644 index 000000000..397a18f91 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionalConfigTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.transaction; + +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.common.module.NitriteModule; +import org.dizitart.no2.exceptions.IndexingException; +import org.dizitart.no2.store.NitriteStore; +import org.dizitart.no2.store.memory.InMemoryConfig; +import org.junit.Test; + +import java.util.HashSet; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class TransactionalConfigTest { + @Test + public void testConstructor() { + TransactionalConfig actualTransactionalConfig = new TransactionalConfig(new NitriteConfig()); + assertTrue(actualTransactionalConfig.getMigrations().isEmpty()); + assertEquals(1, actualTransactionalConfig.getSchemaVersion().intValue()); + assertNull(actualTransactionalConfig.getNitriteStore()); + } + + @Test + public void testFindIndexer() { + assertThrows(IndexingException.class, + () -> (new TransactionalConfig(new NitriteConfig())).findIndexer("Index Type")); + } + + @Test + public void testLoadModule() { + TransactionalConfig transactionalConfig = new TransactionalConfig(new NitriteConfig()); + NitriteModule nitriteModule = mock(NitriteModule.class); + when(nitriteModule.plugins()).thenReturn(new HashSet<>()); + assertSame(transactionalConfig, transactionalConfig.loadModule(nitriteModule)); + verify(nitriteModule, times(2)).plugins(); + } + + @Test + public void testAutoConfigure() { + TransactionalConfig transactionalConfig = new TransactionalConfig(new NitriteConfig()); + transactionalConfig.autoConfigure(); + NitriteStore nitriteStore = transactionalConfig.getNitriteStore(); + assertTrue(nitriteStore instanceof org.dizitart.no2.store.memory.InMemoryStore); + assertFalse(nitriteStore.isClosed()); + assertTrue(((InMemoryConfig) nitriteStore.getStoreConfig()).eventListeners().isEmpty()); + } + + @Test + public void testNitriteMapper() { + assertNull((new TransactionalConfig(new NitriteConfig())).nitriteMapper()); + } + + @Test + public void testGetNitriteStore() { + assertNull((new TransactionalConfig(new NitriteConfig())).getNitriteStore()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionalMapTest.java b/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionalMapTest.java new file mode 100644 index 000000000..88c794f7b --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionalMapTest.java @@ -0,0 +1,515 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.transaction; + +import org.dizitart.no2.store.StoreConfig; +import org.dizitart.no2.store.memory.InMemoryMap; +import org.dizitart.no2.store.memory.InMemoryStore; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class TransactionalMapTest { + @Test + public void testContainsKey() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary2, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + assertFalse(transactionalMap.containsKey("42")); + assertTrue(transactionalMap.entries().toList().isEmpty()); + } + + @Test + public void testContainsKey2() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + + TransactionalMap transactionalMap = new TransactionalMap<>("", primary2, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + transactionalMap.put("42", "42"); + assertTrue(transactionalMap.containsKey("42")); + assertEquals(1, transactionalMap.entries().toList().size()); + } + + @Test + public void testContainsKey3() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + + TransactionalMap transactionalMap = new TransactionalMap<>("", primary2, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + transactionalMap.put("foo", "42"); + assertFalse(transactionalMap.containsKey("42")); + assertEquals(1, transactionalMap.entries().toList().size()); + } + + @Test + public void testGet() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary2, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + assertNull(transactionalMap.get("42")); + assertTrue(transactionalMap.entries().toList().isEmpty()); + } + + @Test + public void testGet2() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary2, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + assertNull(transactionalMap.get(0)); + assertTrue(transactionalMap.entries().toList().isEmpty()); + } + + @Test + public void testClear() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary2, + new InMemoryStore()); + transactionalMap.clear(); + assertTrue(transactionalMap.entries().toList().isEmpty()); + assertEquals(0L, transactionalMap.size()); + assertEquals(4, transactionalMap.getAttributes().getAttributes().size()); + } + + @Test + public void testValues() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary2, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + assertTrue(transactionalMap.values().toList().isEmpty()); + assertTrue(transactionalMap.entries().toList().isEmpty()); + } + + @Test + public void testRemove() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary2, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + assertNull(transactionalMap.remove("42")); + assertTrue(transactionalMap.entries().toList().isEmpty()); + } + + @Test + public void testRemove2() { + InMemoryMap primary = new InMemoryMap<>("Map Name", + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + assertNull(transactionalMap.remove("42")); + assertTrue(transactionalMap.entries().toList().isEmpty()); + } + + @Test + public void testRemove3() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + + TransactionalMap transactionalMap = new TransactionalMap<>("", primary2, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + transactionalMap.put("42", "42"); + assertEquals("42", transactionalMap.remove("42")); + assertTrue(transactionalMap.entries().toList().isEmpty()); + assertEquals(0L, transactionalMap.size()); + } + + @Test + public void testRemove4() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + + TransactionalMap transactionalMap = new TransactionalMap<>("", primary2, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + transactionalMap.put("", "42"); + assertNull(transactionalMap.remove("42")); + assertEquals(1, transactionalMap.entries().toList().size()); + } + + @Test + public void testKeys() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary2, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + assertTrue(transactionalMap.keys().toList().isEmpty()); + assertTrue(transactionalMap.entries().toList().isEmpty()); + } + + @Test + public void testPut() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary2, + new InMemoryStore()); + transactionalMap.put("42", "42"); + assertEquals(1, transactionalMap.entries().toList().size()); + assertEquals(1L, transactionalMap.size()); + assertEquals(4, transactionalMap.getAttributes().getAttributes().size()); + } + + @Test + public void testSize() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary2, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + assertEquals(0L, transactionalMap.size()); + assertTrue(transactionalMap.entries().toList().isEmpty()); + } + + @Test + public void testPutIfAbsent() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary2, + new InMemoryStore()); + assertNull(transactionalMap.putIfAbsent("Key", "Value")); + assertEquals(1, transactionalMap.entries().toList().size()); + assertEquals(1L, transactionalMap.size()); + assertEquals(4, transactionalMap.getAttributes().getAttributes().size()); + } + + @Test + public void testEntries() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + assertTrue((new TransactionalMap<>("Map Name", primary2, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null))))).entries() + .toList() + .isEmpty()); + } + + @Test + public void testReversedEntries() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary2, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + assertTrue(transactionalMap.reversedEntries().toList().isEmpty()); + assertTrue(transactionalMap.entries().toList().isEmpty()); + } + + @Test + public void testHigherKey() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary2, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + assertNull(transactionalMap.higherKey("42")); + assertTrue(transactionalMap.entries().toList().isEmpty()); + } + + @Test + public void testHigherKey2() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + + TransactionalMap transactionalMap = new TransactionalMap<>(null, primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + transactionalMap.putIfAbsent("Key", "Value"); + TransactionalMap transactionalMap1 = new TransactionalMap<>("Map Name", + transactionalMap, new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + assertEquals("Key", transactionalMap1.higherKey("42")); + assertEquals(1, transactionalMap1.entries().toList().size()); + } + + @Test + public void testCeilingKey() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary2, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + assertNull(transactionalMap.ceilingKey("42")); + assertTrue(transactionalMap.entries().toList().isEmpty()); + } + + @Test + public void testCeilingKey2() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + + TransactionalMap transactionalMap = new TransactionalMap<>(null, primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + transactionalMap.put("42", "42"); + TransactionalMap transactionalMap1 = new TransactionalMap<>("Map Name", + transactionalMap, new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + assertEquals("42", transactionalMap1.ceilingKey("42")); + assertEquals(1, transactionalMap1.entries().toList().size()); + } + + @Test + public void testLowerKey() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary2, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + assertNull(transactionalMap.lowerKey("42")); + assertTrue(transactionalMap.entries().toList().isEmpty()); + } + + @Test + public void testFloorKey() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary2, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + assertNull(transactionalMap.floorKey("42")); + assertTrue(transactionalMap.entries().toList().isEmpty()); + } + + @Test + public void testFloorKey2() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + + TransactionalMap transactionalMap = new TransactionalMap<>(null, primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + transactionalMap.put("42", "42"); + TransactionalMap transactionalMap1 = new TransactionalMap<>("Map Name", + transactionalMap, new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + assertEquals("42", transactionalMap1.floorKey("42")); + assertEquals(1, transactionalMap1.entries().toList().size()); + } + + @Test + public void testIsEmpty() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary2, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + assertTrue(transactionalMap.isEmpty()); + assertTrue(transactionalMap.entries().toList().isEmpty()); + } + + @Test + public void testIsEmpty2() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + + TransactionalMap transactionalMap = new TransactionalMap<>("", primary2, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + transactionalMap.put("42", "42"); + assertFalse(transactionalMap.isEmpty()); + assertEquals(1, transactionalMap.entries().toList().size()); + } + + @Test + public void testIsEmpty3() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + + TransactionalMap transactionalMap = new TransactionalMap<>("", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + transactionalMap.put("42", "42"); + TransactionalMap transactionalMap1 = new TransactionalMap<>("Map Name", + transactionalMap, new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + assertFalse(transactionalMap1.isEmpty()); + assertEquals(1, transactionalMap1.entries().toList().size()); + } + + @Test + public void testDrop() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary2, + new InMemoryStore()); + transactionalMap.drop(); + assertTrue(transactionalMap.entries().toList().isEmpty()); + assertEquals(0L, transactionalMap.size()); + assertEquals(4, transactionalMap.getAttributes().getAttributes().size()); + } + + @Test + public void testClose() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary2, + new InMemoryStore()); + transactionalMap.close(); + assertTrue(transactionalMap.entries().toList().isEmpty()); + assertEquals(0L, transactionalMap.size()); + assertEquals(4, transactionalMap.getAttributes().getAttributes().size()); + } + + @Test + public void testConstructor() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalStore transactionalStore = new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary2, + transactionalStore); + TransactionalStore transactionalStore1 = new TransactionalStore<>( + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + TransactionalMap actualTransactionalMap = new TransactionalMap<>("Map Name", + transactionalMap, transactionalStore1); + assertEquals("Map Name", actualTransactionalMap.getName()); + assertEquals("Map Name", transactionalMap.getName()); + assertSame(transactionalStore1, actualTransactionalMap.getStore()); + assertSame(transactionalStore, transactionalMap.getStore()); + } + + @Test + public void testConstructor2() { + TransactionalMap primary = new TransactionalMap<>("Map Name", null, null); + TransactionalMap primary1 = new TransactionalMap<>("Map Name", primary, + new TransactionalStore<>(null)); + TransactionalMap primary2 = new TransactionalMap<>("Map Name", primary1, + new TransactionalStore<>(new TransactionalStore<>(null))); + TransactionalMap transactionalMap = new TransactionalMap<>("Map Name", primary2, + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + TransactionalStore transactionalStore = new TransactionalStore<>( + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + TransactionalMap actualTransactionalMap = new TransactionalMap<>("Map Name", + transactionalMap, transactionalStore); + assertTrue(actualTransactionalMap.entries().toList().isEmpty()); + assertEquals(0L, actualTransactionalMap.size()); + assertTrue(actualTransactionalMap.isEmpty()); + assertSame(transactionalStore, actualTransactionalMap.getStore()); + assertEquals("Map Name", actualTransactionalMap.getName()); + assertTrue(transactionalMap.entries().toList().isEmpty()); + } + + @Test + public void testConstructor3() { + TransactionalStore transactionalStore = new TransactionalStore<>( + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null)))); + TransactionalMap actualTransactionalMap = new TransactionalMap<>("Map Name", null, + transactionalStore); + assertTrue(actualTransactionalMap.entries().toList().isEmpty()); + assertEquals(0L, actualTransactionalMap.size()); + assertTrue(actualTransactionalMap.isEmpty()); + assertSame(transactionalStore, actualTransactionalMap.getStore()); + assertEquals("Map Name", actualTransactionalMap.getName()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionalRTreeTest.java b/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionalRTreeTest.java new file mode 100644 index 000000000..024632db3 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionalRTreeTest.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.transaction; + +import org.dizitart.no2.collection.NitriteId; +import org.dizitart.no2.index.BoundingBox; +import org.dizitart.no2.store.memory.InMemoryRTree; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.*; + +public class TransactionalRTreeTest { + + @Test + public void testAdd2() { + TransactionalRTree transactionalRTree = new TransactionalRTree<>( + new InMemoryRTree<>()); + BoundingBox boundingBox = mock(BoundingBox.class); + when(boundingBox.getMaxY()).thenReturn(10.0f); + when(boundingBox.getMinY()).thenReturn(10.0f); + when(boundingBox.getMaxX()).thenReturn(10.0f); + when(boundingBox.getMinX()).thenReturn(10.0f); + transactionalRTree.add(boundingBox, NitriteId.newId()); + verify(boundingBox).getMaxX(); + verify(boundingBox).getMaxY(); + verify(boundingBox).getMinX(); + verify(boundingBox).getMinY(); + assertEquals(1L, transactionalRTree.size()); + } + + @Test + public void testRemove2() { + TransactionalRTree transactionalRTree = new TransactionalRTree<>( + new InMemoryRTree<>()); + BoundingBox boundingBox = mock(BoundingBox.class); + when(boundingBox.getMaxY()).thenReturn(10.0f); + when(boundingBox.getMinY()).thenReturn(10.0f); + when(boundingBox.getMaxX()).thenReturn(10.0f); + when(boundingBox.getMinX()).thenReturn(10.0f); + transactionalRTree.remove(boundingBox, NitriteId.newId()); + verify(boundingBox).getMaxX(); + verify(boundingBox).getMaxY(); + verify(boundingBox).getMinX(); + verify(boundingBox).getMinY(); + assertEquals(0L, transactionalRTree.size()); + } + + @Test + public void testFindIntersectingKeys() { + TransactionalRTree transactionalRTree = new TransactionalRTree<>( + new InMemoryRTree<>()); + BoundingBox boundingBox = mock(BoundingBox.class); + when(boundingBox.getMaxY()).thenReturn(10.0f); + when(boundingBox.getMinY()).thenReturn(10.0f); + when(boundingBox.getMaxX()).thenReturn(10.0f); + when(boundingBox.getMinX()).thenReturn(10.0f); + assertTrue(transactionalRTree.findIntersectingKeys(boundingBox).toList().isEmpty()); + verify(boundingBox, times(2)).getMaxX(); + verify(boundingBox, times(2)).getMaxY(); + verify(boundingBox, times(2)).getMinX(); + verify(boundingBox, times(2)).getMinY(); + } + + @Test + public void testFindIntersectingKeys2() { + TransactionalRTree transactionalRTree = new TransactionalRTree<>( + new TransactionalRTree<>(new InMemoryRTree<>())); + BoundingBox boundingBox = mock(BoundingBox.class); + when(boundingBox.getMaxY()).thenReturn(10.0f); + when(boundingBox.getMinY()).thenReturn(10.0f); + when(boundingBox.getMaxX()).thenReturn(10.0f); + when(boundingBox.getMinX()).thenReturn(10.0f); + assertTrue(transactionalRTree.findIntersectingKeys(boundingBox).toList().isEmpty()); + verify(boundingBox, times(3)).getMaxX(); + verify(boundingBox, times(3)).getMaxY(); + verify(boundingBox, times(3)).getMinX(); + verify(boundingBox, times(3)).getMinY(); + } + + @Test + public void testFindContainedKeys() { + TransactionalRTree transactionalRTree = new TransactionalRTree<>( + new InMemoryRTree<>()); + BoundingBox boundingBox = mock(BoundingBox.class); + when(boundingBox.getMaxY()).thenReturn(10.0f); + when(boundingBox.getMinY()).thenReturn(10.0f); + when(boundingBox.getMaxX()).thenReturn(10.0f); + when(boundingBox.getMinX()).thenReturn(10.0f); + assertTrue(transactionalRTree.findContainedKeys(boundingBox).toList().isEmpty()); + verify(boundingBox, times(2)).getMaxX(); + verify(boundingBox, times(2)).getMaxY(); + verify(boundingBox, times(2)).getMinX(); + verify(boundingBox, times(2)).getMinY(); + } + + @Test + public void testFindContainedKeys2() { + TransactionalRTree transactionalRTree = new TransactionalRTree<>( + new TransactionalRTree<>(new InMemoryRTree<>())); + BoundingBox boundingBox = mock(BoundingBox.class); + when(boundingBox.getMaxY()).thenReturn(10.0f); + when(boundingBox.getMinY()).thenReturn(10.0f); + when(boundingBox.getMaxX()).thenReturn(10.0f); + when(boundingBox.getMinX()).thenReturn(10.0f); + assertTrue(transactionalRTree.findContainedKeys(boundingBox).toList().isEmpty()); + verify(boundingBox, times(3)).getMaxX(); + verify(boundingBox, times(3)).getMaxY(); + verify(boundingBox, times(3)).getMinX(); + verify(boundingBox, times(3)).getMinY(); + } + + @Test + public void testSize() { + assertEquals(0L, (new TransactionalRTree<>(new InMemoryRTree<>())).size()); + } + + @Test + public void testClose() { + TransactionalRTree transactionalRTree = new TransactionalRTree<>( + new InMemoryRTree<>()); + transactionalRTree.close(); + assertEquals(0L, transactionalRTree.size()); + } + + @Test + public void testConstructor() { + assertEquals(0L, (new TransactionalRTree<>(new InMemoryRTree<>())).size()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionalStoreTest.java b/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionalStoreTest.java new file mode 100644 index 000000000..85e413192 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/transaction/TransactionalStoreTest.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.transaction; + +import org.dizitart.no2.NitriteConfig; +import org.dizitart.no2.exceptions.InvalidOperationException; +import org.dizitart.no2.store.NitriteStore; +import org.dizitart.no2.store.StoreConfig; +import org.dizitart.no2.store.events.StoreEventListener; +import org.dizitart.no2.store.memory.InMemoryConfig; +import org.dizitart.no2.store.memory.InMemoryRTree; +import org.dizitart.no2.store.memory.InMemoryStore; +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class TransactionalStoreTest { + @Test + public void testCommit() { + assertThrows(InvalidOperationException.class, + () -> (new TransactionalStore<>(new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(null))))).commit()); + } + + @Test + public void testClose() throws Exception { + TransactionalStore transactionalStore = new TransactionalStore<>( + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(new InMemoryStore())))); + transactionalStore.close(); + assertNotNull(transactionalStore.getCatalog()); + } + + @Test + public void testHasMap() { + NitriteStore nitriteStore = (NitriteStore) mock(NitriteStore.class); + when(nitriteStore.hasMap(anyString())).thenReturn(true); + TransactionalStore transactionalStore = new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(nitriteStore))); + assertTrue(transactionalStore.hasMap("Map Name")); + verify(nitriteStore).hasMap(anyString()); + assertNull(transactionalStore.getStoreVersion()); + } + + @Test + public void testHasMap2() { + NitriteStore nitriteStore = (NitriteStore) mock(NitriteStore.class); + when(nitriteStore.hasMap(anyString())).thenReturn(false); + TransactionalStore transactionalStore = new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(nitriteStore))); + assertFalse(transactionalStore.hasMap("Map Name")); + verify(nitriteStore).hasMap(anyString()); + assertNull(transactionalStore.getStoreVersion()); + } + + @Test + public void testOpenRTree() { + NitriteStore nitriteStore = (NitriteStore) mock(NitriteStore.class); + when(nitriteStore.openRTree(anyString(), any(), any())) + .thenReturn(new InMemoryRTree<>()); + when(nitriteStore.hasMap(anyString())).thenReturn(true); + TransactionalStore transactionalStore = new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(nitriteStore))); + Class keyType = Object.class; + assertEquals(0L, transactionalStore.openRTree("R Tree Name", keyType, Object.class).size()); + verify(nitriteStore, times(3)).hasMap(anyString()); + verify(nitriteStore).openRTree(anyString(), any(), any()); + assertNull(transactionalStore.getStoreVersion()); + } + + @Test + public void testOpenRTree2() { + NitriteStore nitriteStore = (NitriteStore) mock(NitriteStore.class); + when(nitriteStore.openRTree(anyString(), any(), any())) + .thenReturn(new InMemoryRTree<>()); + when(nitriteStore.hasMap(anyString())).thenReturn(false); + TransactionalStore transactionalStore = new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(nitriteStore))); + Class keyType = Object.class; + assertEquals(0L, transactionalStore.openRTree("R Tree Name", keyType, Object.class).size()); + verify(nitriteStore).hasMap(anyString()); + assertNull(transactionalStore.getStoreVersion()); + } + + @Test + public void testGetStoreVersion() { + NitriteStore nitriteStore = (NitriteStore) mock(NitriteStore.class); + when(nitriteStore.getStoreVersion()).thenReturn("foo"); + assertEquals("foo", (new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(nitriteStore)))).getStoreVersion()); + verify(nitriteStore).getStoreVersion(); + } + + @Test + public void testConstructor() { + TransactionalStore transactionalStore = new TransactionalStore<>(new InMemoryStore()); + TransactionalStore actualTransactionalStore = new TransactionalStore<>(transactionalStore); + actualTransactionalStore.initialize(new NitriteConfig()); + actualTransactionalStore.openOrCreate(); + actualTransactionalStore.subscribe(mock(StoreEventListener.class)); + actualTransactionalStore.unsubscribe(mock(StoreEventListener.class)); + assertTrue(transactionalStore.hasUnsavedChanges()); + assertTrue(actualTransactionalStore.hasUnsavedChanges()); + assertFalse(transactionalStore.isClosed()); + assertFalse(actualTransactionalStore.isClosed()); + assertFalse(transactionalStore.isReadOnly()); + assertFalse(actualTransactionalStore.isReadOnly()); + } + + @Test + public void testConstructor2() { + TransactionalStore transactionalStore = new TransactionalStore<>( + new TransactionalStore<>( + new TransactionalStore<>(new TransactionalStore<>(new InMemoryStore())))); + TransactionalStore actualTransactionalStore = new TransactionalStore<>(transactionalStore); + assertNotNull(actualTransactionalStore.getCatalog()); + assertFalse(actualTransactionalStore.isReadOnly()); + assertFalse(actualTransactionalStore.isClosed()); + assertTrue(actualTransactionalStore.hasUnsavedChanges()); + assertNull(actualTransactionalStore.getStoreConfig()); + assertNotNull(transactionalStore.getCatalog()); + assertFalse(transactionalStore.isReadOnly()); + assertFalse(transactionalStore.isClosed()); + assertTrue(transactionalStore.hasUnsavedChanges()); + assertNull(transactionalStore.getStoreConfig()); + } +} + diff --git a/nitrite/src/test/java/org/dizitart/no2/transaction/TxData.java b/nitrite/src/test/java/org/dizitart/no2/transaction/TxData.java deleted file mode 100644 index f5e7c02cf..000000000 --- a/nitrite/src/test/java/org/dizitart/no2/transaction/TxData.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.transaction; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; -import org.dizitart.no2.repository.annotations.Id; - -/** - * @author Anindya Chatterjee. - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -class TxData implements Mappable { - @Id - private Long id; - private String name; - - @Override - public Document write(NitriteMapper mapper) { - return Document.createDocument("id", id) - .put("name", name); - } - - @Override - public void read(NitriteMapper mapper, Document document) { - id = document.get("id", Long.class); - name = document.get("name", String.class); - } -} diff --git a/nitrite/src/test/java/org/dizitart/no2/transaction/UndoEntryTest.java b/nitrite/src/test/java/org/dizitart/no2/transaction/UndoEntryTest.java new file mode 100644 index 000000000..4f6c8b4a0 --- /dev/null +++ b/nitrite/src/test/java/org/dizitart/no2/transaction/UndoEntryTest.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2017-2021 Nitrite author or authors. + * + * Licensed 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.dizitart.no2.transaction; + +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; + +public class UndoEntryTest { + @Test + public void testCanEqual() { + assertFalse((new UndoEntry()).canEqual("Other")); + } + + @Test + public void testCanEqual2() { + UndoEntry undoEntry = new UndoEntry(); + assertTrue(undoEntry.canEqual(new UndoEntry())); + } + + @Test + public void testConstructor() { + UndoEntry actualUndoEntry = new UndoEntry(); + actualUndoEntry.setCollectionName("Collection Name"); + actualUndoEntry.setRollback(mock(Command.class)); + assertEquals("Collection Name", actualUndoEntry.getCollectionName()); + } + + @Test + public void testEquals() { + assertFalse((new UndoEntry()).equals("42")); + } + + @Test + public void testEquals2() { + UndoEntry undoEntry = new UndoEntry(); + assertTrue(undoEntry.equals(new UndoEntry())); + } + + @Test + public void testEquals3() { + UndoEntry undoEntry = new UndoEntry(); + undoEntry.setRollback(mock(Command.class)); + assertFalse(undoEntry.equals(new UndoEntry())); + } + + @Test + public void testEquals4() { + UndoEntry undoEntry = new UndoEntry(); + + UndoEntry undoEntry1 = new UndoEntry(); + undoEntry1.setRollback(mock(Command.class)); + assertFalse(undoEntry.equals(undoEntry1)); + } + + @Test + public void testEquals5() { + UndoEntry undoEntry = new UndoEntry(); + undoEntry.setCollectionName("Collection Name"); + assertFalse(undoEntry.equals(new UndoEntry())); + } + + @Test + public void testEquals6() { + UndoEntry undoEntry = new UndoEntry(); + + UndoEntry undoEntry1 = new UndoEntry(); + undoEntry1.setCollectionName("Collection Name"); + assertFalse(undoEntry.equals(undoEntry1)); + } + + @Test + public void testEquals7() { + UndoEntry undoEntry = new UndoEntry(); + undoEntry.setCollectionName("Collection Name"); + + UndoEntry undoEntry1 = new UndoEntry(); + undoEntry1.setCollectionName("Collection Name"); + assertTrue(undoEntry.equals(undoEntry1)); + } + + @Test + public void testHashCode() { + assertEquals(6061, (new UndoEntry()).hashCode()); + } + + @Test + public void testHashCode3() { + UndoEntry undoEntry = new UndoEntry(); + undoEntry.setCollectionName("Collection Name"); + assertEquals(244972291, undoEntry.hashCode()); + } +} + diff --git a/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/Builder.kt b/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/Builder.kt index b49dfb100..b8ccac4cd 100644 --- a/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/Builder.kt +++ b/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/Builder.kt @@ -19,8 +19,8 @@ package org.dizitart.kno2 import org.dizitart.no2.Nitrite import org.dizitart.no2.NitriteBuilder import org.dizitart.no2.NitriteConfig -import org.dizitart.no2.module.NitriteModule -import org.dizitart.no2.module.NitriteModule.module +import org.dizitart.no2.common.module.NitriteModule +import org.dizitart.no2.common.module.NitriteModule.module import org.dizitart.no2.spatial.SpatialIndexer /** diff --git a/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/Documents.kt b/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/Documents.kt index dfa626f0b..973446270 100644 --- a/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/Documents.kt +++ b/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/Documents.kt @@ -48,8 +48,18 @@ fun documentOf(pair: Pair): Document { return createDocument(pair.first, pair.second)!! } +/** + * Checks if a [Document] is empty. + * + * @return boolean value + */ fun Document.isEmpty() = this.size() == 0 +/** + * Checks if a [Document] is not empty. + * + * @return boolean value + */ fun Document.isNotEmpty() = !this.isEmpty() /** diff --git a/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/KNO2JacksonMapper.kt b/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/KNO2JacksonMapper.kt index 2e6faa0be..6e71cdb61 100644 --- a/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/KNO2JacksonMapper.kt +++ b/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/KNO2JacksonMapper.kt @@ -21,8 +21,8 @@ import com.fasterxml.jackson.databind.SerializationFeature import com.fasterxml.jackson.datatype.jdk8.Jdk8Module import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule import com.fasterxml.jackson.module.kotlin.KotlinModule -import org.dizitart.no2.mapper.JacksonMapper -import org.dizitart.no2.mapper.JacksonExtension +import org.dizitart.no2.common.mapper.JacksonMapper +import org.dizitart.no2.common.mapper.JacksonExtension import org.dizitart.no2.spatial.mapper.GeometryExtension import java.time.ZoneId import java.time.chrono.ChronoPeriod diff --git a/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/KNO2Module.kt b/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/KNO2Module.kt index c247601f3..c7cce31f1 100644 --- a/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/KNO2Module.kt +++ b/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/KNO2Module.kt @@ -16,9 +16,10 @@ package org.dizitart.kno2 -import org.dizitart.no2.mapper.JacksonExtension -import org.dizitart.no2.module.NitriteModule -import org.dizitart.no2.module.NitritePlugin +import org.dizitart.no2.common.util.Iterables.setOf +import org.dizitart.no2.common.mapper.JacksonExtension +import org.dizitart.no2.common.module.NitriteModule +import org.dizitart.no2.common.module.NitritePlugin import org.dizitart.no2.spatial.SpatialIndexer /** diff --git a/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/Nitrite.kt b/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/Nitrite.kt index f15471c53..bc5759722 100644 --- a/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/Nitrite.kt +++ b/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/Nitrite.kt @@ -52,7 +52,9 @@ fun Nitrite.getCollection(name: String, op: (NitriteCollection.() -> Unit)? = nu * @param [op] repository builder block * @return the object repository of type [T] */ -inline fun Nitrite.getRepository(noinline op: (ObjectRepository.() -> Unit)? = null): ObjectRepository { +inline fun Nitrite.getRepository( + noinline op: (ObjectRepository.() -> Unit)? = null +): ObjectRepository { val repository = this.getRepository(T::class.java) op?.invoke(repository) return repository @@ -68,17 +70,19 @@ inline fun Nitrite.getRepository(noinline op: (ObjectRepositor * @param [op] repository builder block * @return the object repository of type [T] */ -inline fun Nitrite.getRepository(key: String, noinline op: (ObjectRepository.() -> Unit)? = null): ObjectRepository { +inline fun Nitrite.getRepository( + key: String, + noinline op: (ObjectRepository.() -> Unit)? = null +): ObjectRepository { val repository = this.getRepository(T::class.java, key) op?.invoke(repository) return repository } /** - * Creates an [IndexOptions] with the specified [indexType] and [async] flag. + * Creates an [IndexOptions] with the specified [indexType]. * * @param [indexType] the type of index to be created. - * @param [async] if set to [true] then the index would be created asynchronously; otherwise synchronously. * @return a new [IndexOptions] */ -fun option(indexType: String = IndexType.Unique, async: Boolean = false): IndexOptions = IndexOptions.indexOptions(indexType, async) \ No newline at end of file +fun option(indexType: String = IndexType.UNIQUE): IndexOptions = IndexOptions.indexOptions(indexType) \ No newline at end of file diff --git a/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/filters/Filters.kt b/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/filters/Filters.kt index c15d8d534..6583a008c 100644 --- a/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/filters/Filters.kt +++ b/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/filters/Filters.kt @@ -17,6 +17,8 @@ package org.dizitart.kno2.filters import org.dizitart.no2.filters.Filter +import org.dizitart.no2.filters.Filter.and +import org.dizitart.no2.filters.Filter.or import org.dizitart.no2.filters.FluentFilter import org.locationtech.jts.geom.Coordinate import org.locationtech.jts.geom.Geometry @@ -38,65 +40,73 @@ inline infix fun String.eq(value: T?): Filter = FluentFilter.where(t * Creates an not equality filter which does not matches documents where the value * of a field equals the specified [value]. */ -inline infix fun String.notEq(value: T?): Filter = FluentFilter.where(this).notEq(value) +inline infix fun String.notEq(value: T?): Filter = + FluentFilter.where(this).notEq(value) /** * Creates a greater than filter which matches those documents where the value * of the value is greater than (i.e. >) the specified [value]. */ -inline infix fun > String.gt(value: T?): Filter = FluentFilter.where(this).gt(value) +inline infix fun > String.gt(value: T?): Filter = + FluentFilter.where(this).gt(value) /** * Creates a greater equal filter which matches those documents where the value * of the value is greater than or equals to (i.e. >=) the specified [value]. */ -inline infix fun > String.gte(value: T?): Filter = FluentFilter.where(this).gte(value) +inline infix fun > String.gte(value: T?): Filter = + FluentFilter.where(this).gte(value) /** * Creates a lesser than filter which matches those documents where the value * of the value is less than (i.e. <) the specified [value]. */ -inline infix fun > String.lt(value: T?): Filter = FluentFilter.where(this).lt(value) +inline infix fun > String.lt(value: T?): Filter = + FluentFilter.where(this).lt(value) /** * Creates a lesser equal filter which matches those documents where the value * of the value is lesser than or equals to (i.e. <=) the specified [value]. */ -inline infix fun > String.lte(value: T?): Filter = FluentFilter.where(this).lte(value) +inline infix fun > String.lte(value: T?): Filter = + FluentFilter.where(this).lte(value) /** * Creates a between filter which matches those documents where the value * of the field is within the specified bound including the end values. */ -inline fun > String.between(lowerBound: T, upperBound: T): Filter - = FluentFilter.where(this).between(lowerBound, upperBound) +inline fun > String.between(lowerBound: T, upperBound: T): Filter = + FluentFilter.where(this).between(lowerBound, upperBound) /** * Creates a between filter which matches those documents where the value * of the field is within the specified bound. * */ -inline fun > String.between(lowerBound: T, upperBound: T, inclusive: Boolean): Filter - = FluentFilter.where(this).between(lowerBound, upperBound, inclusive) +inline fun > String.between(lowerBound: T, upperBound: T, inclusive: Boolean): Filter = + FluentFilter.where(this).between(lowerBound, upperBound, inclusive) /** * Creates a between filter which matches those documents where the value * of the field is within the specified bound. * */ -inline fun > String.between(lowerBound: T, upperBound: T, lowerInclusive: Boolean, - upperInclusive: Boolean): Filter - = FluentFilter.where(this).between(lowerBound, upperBound, lowerInclusive, upperInclusive) +inline fun > String.between( + lowerBound: T, upperBound: T, lowerInclusive: Boolean, + upperInclusive: Boolean +): Filter = FluentFilter.where(this).between(lowerBound, upperBound, lowerInclusive, upperInclusive) /** * Creates an in filter which matches the documents where * the value of a field equals any value in the specified array of [values]. */ -inline infix fun > String.within(values: Array): Filter = FluentFilter.where(this).`in`(*values) +inline infix fun > String.within(values: Array): Filter = + FluentFilter.where(this).`in`(*values) /** * Creates an in filter which matches the documents where * the value of a field equals any value in the specified array of [values]. */ -inline infix fun > String.within(values: Iterable): Filter = FluentFilter.where(this).`in`(*(values.toList().toTypedArray())) +inline infix fun > String.within(values: Iterable): Filter = + FluentFilter.where(this).`in`(*(values.toList().toTypedArray())) /** * Creates an element match filter that matches documents that contain an array @@ -116,79 +126,108 @@ infix fun String.text(value: String?): Filter = FluentFilter.where(this).text(va */ infix fun String.regex(value: String?): Filter = FluentFilter.where(this).regex(value) -inline infix fun String.within(value: T?): Filter = org.dizitart.no2.spatial.FluentFilter.where(this).within(value) +/** + * Creates a spatial filter which matches documents where the spatial data + * of a field is within the specified Geometry value. + */ +inline infix fun String.within(value: T?): Filter = + org.dizitart.no2.spatial.FluentFilter.where(this).within(value) -inline infix fun String.intersects(value: T?): Filter = org.dizitart.no2.spatial.FluentFilter.where(this).intersects(value) +/** + * Creates an spatial filter which matches documents where the spatial data + * of a field intersects the specified Geometry value. + */ +inline infix fun String.intersects(value: T?): Filter = + org.dizitart.no2.spatial.FluentFilter.where(this).intersects(value) -inline fun String.near(value: T?, distance: Double): Filter = org.dizitart.no2.spatial.FluentFilter.where(this).near(value, distance) +/** + * Creates a spatial filter which matches documents where the spatial data + * of a field is near the specified coordinate. + */ +inline fun String.near(value: T?, distance: Double): Filter = + org.dizitart.no2.spatial.FluentFilter.where(this).near(value, distance) -inline fun String.near(value: T?, distance: Double): Filter = org.dizitart.no2.spatial.FluentFilter.where(this).near(value, distance) +/** + * Creates a spatial filter which matches documents where the spatial data + * of a field is near the specified point. + */ +inline fun String.near(value: T?, distance: Double): Filter = + org.dizitart.no2.spatial.FluentFilter.where(this).near(value, distance) /** * Creates an and filter which performs a logical AND operation on two filters and selects * the documents that satisfy both filters. */ -inline infix fun Filter.and(filter: T): Filter = this.and(filter) +inline infix fun Filter.and(filter: T): Filter = and(this, filter) /** * Creates an or filter which performs a logical OR operation on two filters and selects * the documents that satisfy at least one of the filter. */ -inline infix fun Filter.or(filter: T): Filter = this.or(filter) +inline infix fun Filter.or(filter: T): Filter = or(this, filter) /** * Creates an equality filter which matches objects where the value * of a property equals the specified [value]. */ -inline infix fun KProperty.eq(value: T?): Filter = FluentFilter.where(this.name).eq(value) +inline infix fun KProperty.eq(value: T?): Filter = + FluentFilter.where(this.name).eq(value) /** * Creates an not equality filter which does not matches objects where the value * of a property equals the specified [value]. */ -inline infix fun KProperty.notEq(value: T?): Filter = FluentFilter.where(this.name).notEq(value) +inline infix fun KProperty.notEq(value: T?): Filter = + FluentFilter.where(this.name).notEq(value) /** * Creates a greater than filter which matches those objects where the value * of the property is greater than (i.e. >) the specified [value]. */ -inline infix fun > KProperty.gt(value: T?): Filter = FluentFilter.where(this.name).gt(value) +inline infix fun > KProperty.gt(value: T?): Filter = + FluentFilter.where(this.name).gt(value) /** * Creates a greater equal filter which matches those objects where the value * of the property is greater than or equals to (i.e. >=) the specified [value]. */ -inline infix fun > KProperty.gte(value: T?): Filter = FluentFilter.where(this.name).gte(value) +inline infix fun > KProperty.gte(value: T?): Filter = + FluentFilter.where(this.name).gte(value) /** * Creates a lesser than filter which matches those objects where the value * of the property is less than (i.e. <) the specified [value]. */ -inline infix fun > KProperty.lt(value: T?): Filter = FluentFilter.where(this.name).lt(value) +inline infix fun > KProperty.lt(value: T?): Filter = + FluentFilter.where(this.name).lt(value) /** * Creates a lesser equal filter which matches those objects where the value * of the property is lesser than or equals to (i.e. <=) the specified [value]. */ -inline infix fun > KProperty.lte(value: T?): Filter = FluentFilter.where(this.name).lte(value) +inline infix fun > KProperty.lte(value: T?): Filter = + FluentFilter.where(this.name).lte(value) /** * Creates an in filter which matches the objects where * the value of a property equals any value in the specified array of [values]. */ -inline infix fun > KProperty.within(values: Array): Filter = FluentFilter.where(this.name).`in`(*values) +inline infix fun > KProperty.within(values: Array): Filter = + FluentFilter.where(this.name).`in`(*values) /** * Creates an in filter which matches the objects where * the value of a property equals any value in the specified list of [values]. */ -inline infix fun > KProperty.within(values: Iterable): Filter = FluentFilter.where(this.name).`in`(*(values.toList().toTypedArray())) +inline infix fun > KProperty.within(values: Iterable): Filter = + FluentFilter.where(this.name).`in`(*(values.toList().toTypedArray())) /** * Creates an element match filter that matches objects that contain an array * value with at least one element that matches the specified [filter]. */ -inline infix fun KProperty?>.elemMatch(filter: Filter): Filter = FluentFilter.where(this.name).elemMatch(filter) +inline infix fun KProperty?>.elemMatch(filter: Filter): Filter = + FluentFilter.where(this.name).elemMatch(filter) /** * Creates a text filter which performs a text search on the content of the property @@ -202,10 +241,30 @@ infix fun KProperty.text(value: String?): Filter = FluentFilter.where(t */ infix fun KProperty.regex(value: String?): Filter = FluentFilter.where(this.name).regex(value) -inline infix fun KProperty.within(value: T?): Filter = org.dizitart.no2.spatial.FluentFilter.where(this.name).within(value) +/** + * Creates a spatial filter which matches documents where the spatial data + * of a field is within the specified Geometry value. + */ +inline infix fun KProperty.within(value: T?): Filter = + org.dizitart.no2.spatial.FluentFilter.where(this.name).within(value) -inline infix fun KProperty.intersects(value: T?): Filter = org.dizitart.no2.spatial.FluentFilter.where(this.name).intersects(value) +/** + * Creates an spatial filter which matches documents where the spatial data + * of a field intersects the specified Geometry value. + */ +inline infix fun KProperty.intersects(value: T?): Filter = + org.dizitart.no2.spatial.FluentFilter.where(this.name).intersects(value) -inline fun KProperty.near(value: Point, distance: Double): Filter = org.dizitart.no2.spatial.FluentFilter.where(this.name).near(value, distance) +/** + * Creates a spatial filter which matches documents where the spatial data + * of a field is near the specified coordinate. + */ +inline fun KProperty.near(value: Point, distance: Double): Filter = + org.dizitart.no2.spatial.FluentFilter.where(this.name).near(value, distance) -inline fun KProperty.near(value: Coordinate, distance: Double): Filter = org.dizitart.no2.spatial.FluentFilter.where(this.name).near(value, distance) +/** + * Creates a spatial filter which matches documents where the spatial data + * of a field is near the specified point. + */ +inline fun KProperty.near(value: Coordinate, distance: Double): Filter = + org.dizitart.no2.spatial.FluentFilter.where(this.name).near(value, distance) diff --git a/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/package.md b/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/package.md deleted file mode 100644 index 14e1d7991..000000000 --- a/potassium-nitrite/src/main/kotlin/org/dizitart/kno2/package.md +++ /dev/null @@ -1,3 +0,0 @@ -# Package org.dizitart.kno2 - -Contains useful extensions for nitrite database. \ No newline at end of file diff --git a/potassium-nitrite/src/test/kotlin/org/dizitart/kno2/BackportJavaTimeTest.kt b/potassium-nitrite/src/test/kotlin/org/dizitart/kno2/BackportJavaTimeTest.kt index 07180fd9f..ef8aef206 100644 --- a/potassium-nitrite/src/test/kotlin/org/dizitart/kno2/BackportJavaTimeTest.kt +++ b/potassium-nitrite/src/test/kotlin/org/dizitart/kno2/BackportJavaTimeTest.kt @@ -23,7 +23,7 @@ import com.fasterxml.jackson.databind.module.SimpleModule import org.dizitart.no2.index.IndexType import org.dizitart.no2.repository.annotations.Id import org.dizitart.no2.repository.annotations.Index -import org.dizitart.no2.mapper.JacksonExtension +import org.dizitart.no2.common.mapper.JacksonExtension import org.dizitart.no2.mvstore.MVStoreModule import org.junit.Test import org.threeten.bp.LocalDateTime @@ -39,7 +39,7 @@ import java.util.* class BackportJavaTimeTest { private val dbPath = getRandomTempDbFile() - @Index(value = "time", type = IndexType.NonUnique) + @Index(value = ["time"], type = IndexType.NON_UNIQUE) data class TestData( @Id val id: String = UUID.randomUUID().toString(), val time: LocalDateTime @@ -73,7 +73,7 @@ class BackportJavaTimeTest { } } - override fun getDataTypes(): List> { + override fun getSupportedTypes(): List> { return listOf(LocalDateTime::class.java) } } diff --git a/potassium-nitrite/src/test/kotlin/org/dizitart/kno2/BuilderTest.kt b/potassium-nitrite/src/test/kotlin/org/dizitart/kno2/BuilderTest.kt index b4ddfd3ea..52a466ff4 100644 --- a/potassium-nitrite/src/test/kotlin/org/dizitart/kno2/BuilderTest.kt +++ b/potassium-nitrite/src/test/kotlin/org/dizitart/kno2/BuilderTest.kt @@ -16,14 +16,13 @@ package org.dizitart.kno2 -import org.dizitart.no2.exceptions.SecurityException +import org.dizitart.no2.exceptions.NitriteSecurityException import org.dizitart.no2.index.NitriteTextIndexer import org.dizitart.no2.index.fulltext.UniversalTextTokenizer -import org.dizitart.no2.module.NitriteModule.module +import org.dizitart.no2.common.module.NitriteModule.module import org.dizitart.no2.mvstore.MVStoreModule import org.junit.Assert.* import org.junit.Test -import java.io.File /** * @@ -65,14 +64,14 @@ class BuilderTest : BaseTest() { assertFalse(db?.isClosed!!) } - @Test(expected = SecurityException::class) + @Test(expected = NitriteSecurityException::class) fun testBuilderNoUser() { db = nitrite("", "password") { loadModule(MVStoreModule(fileName)) } } - @Test(expected = SecurityException::class) + @Test(expected = NitriteSecurityException::class) fun testBuilderNoPassword() { db = nitrite("user", "") { loadModule(MVStoreModule(fileName)) diff --git a/potassium-nitrite/src/test/kotlin/org/dizitart/kno2/FilterTest.kt b/potassium-nitrite/src/test/kotlin/org/dizitart/kno2/FilterTest.kt index 34ccf7f77..3286e8f67 100644 --- a/potassium-nitrite/src/test/kotlin/org/dizitart/kno2/FilterTest.kt +++ b/potassium-nitrite/src/test/kotlin/org/dizitart/kno2/FilterTest.kt @@ -21,6 +21,7 @@ import org.dizitart.kno2.filters.* import org.dizitart.no2.collection.Document import org.dizitart.no2.common.Constants import org.dizitart.no2.index.IndexOptions +import org.dizitart.no2.index.IndexOptions.indexOptions import org.dizitart.no2.index.IndexType import org.dizitart.no2.mvstore.MVStoreModule import org.dizitart.no2.spatial.SpatialIndexer @@ -155,7 +156,7 @@ class FilterTest : BaseTest() { @Test fun testText() { db?.getCollection("test") { - createIndex("a", option(IndexType.Fulltext)) + createIndex(option(IndexType.FULL_TEXT), "a") insert(documentOf("a" to "Lorem ipsum dolor"), documentOf("a" to "quick brown fox jumps over lazy dog")) @@ -171,7 +172,7 @@ class FilterTest : BaseTest() { @Test fun testRegex() { db?.getCollection("test") { - createIndex("a", option(IndexType.Fulltext)) + createIndex(option(IndexType.FULL_TEXT), "a") insert(documentOf("a" to "lorem"), documentOf("a" to "dog")) @@ -252,7 +253,7 @@ class FilterTest : BaseTest() { val doc3 = documentOf("key" to 3L).put("location", reader.read("POLYGON ((550 521, 580 540, 570 564, 512 566, 550 521))")) insert(doc1, doc2, doc3) - createIndex("location", IndexOptions.indexOptions(SpatialIndexer.SpatialIndex)) + createIndex(indexOptions(SpatialIndexer.SPATIAL_INDEX), "location") val cursor1 = find("location" intersects search) assertEquals(cursor1.size(), 2) @@ -271,7 +272,7 @@ class FilterTest : BaseTest() { val doc3 = documentOf("key" to 3L).put("location", reader.read("POLYGON ((550 521, 580 540, 570 564, 512 566, 550 521))")) insert(doc1, doc2, doc3) - createIndex("location", IndexOptions.indexOptions(SpatialIndexer.SpatialIndex)) + createIndex(indexOptions(SpatialIndexer.SPATIAL_INDEX), "location") val cursor1 = find("location" within search) assertEquals(cursor1.size(), 1) @@ -290,7 +291,7 @@ class FilterTest : BaseTest() { val doc3 = documentOf("key" to 3L).put("location", reader.read("POLYGON ((550 521, 580 540, 570 564, 512 566, 550 521))")) insert(doc1, doc2, doc3) - createIndex("location", IndexOptions.indexOptions(SpatialIndexer.SpatialIndex)) + createIndex(indexOptions(SpatialIndexer.SPATIAL_INDEX), "location") val cursor1 = find("location".near(search, 20.0)) assertEquals(cursor1.size(), 1) @@ -310,7 +311,7 @@ class FilterTest : BaseTest() { val doc3 = documentOf("key" to 3L).put("location", reader.read("POLYGON ((550 521, 580 540, 570 564, 512 566, 550 521))")) insert(doc1, doc2, doc3) - createIndex("location", IndexOptions.indexOptions(SpatialIndexer.SpatialIndex)) + createIndex(indexOptions(SpatialIndexer.SPATIAL_INDEX), "location") val cursor1 = find("location".near(coordinate, 20.0)) assertEquals(cursor1.size(), 1) diff --git a/potassium-nitrite/src/test/kotlin/org/dizitart/kno2/NitriteTest.kt b/potassium-nitrite/src/test/kotlin/org/dizitart/kno2/NitriteTest.kt index 4e78dc63d..de873a1b9 100644 --- a/potassium-nitrite/src/test/kotlin/org/dizitart/kno2/NitriteTest.kt +++ b/potassium-nitrite/src/test/kotlin/org/dizitart/kno2/NitriteTest.kt @@ -17,10 +17,13 @@ package org.dizitart.kno2 import org.dizitart.kno2.filters.text -import org.dizitart.no2.common.NullOrder +import org.dizitart.no2.collection.FindOptions +import org.dizitart.no2.collection.FindOptions.orderBy +import org.dizitart.no2.collection.FindOptions.skipBy import org.dizitart.no2.common.SortOrder import org.dizitart.no2.exceptions.UniqueConstraintException import org.dizitart.no2.index.IndexOptions +import org.dizitart.no2.index.IndexOptions.indexOptions import org.dizitart.no2.index.IndexType import org.dizitart.no2.mvstore.MVStoreModule import org.dizitart.no2.repository.annotations.Id @@ -77,7 +80,7 @@ class NitriteTest : BaseTest() { @Test fun testIndexOption() { db?.getCollection("test") { - createIndex("id", option(IndexType.Unique, true)) + createIndex(option(IndexType.UNIQUE), "id") assertTrue(hasIndex("id")) assertFalse(hasIndex("name")) } @@ -91,14 +94,14 @@ class NitriteTest : BaseTest() { documentOf("a" to 3), documentOf("a" to 4), documentOf("a" to 5)) - var cursor = find().skipLimit(0, 2) + var cursor = find(skipBy(0).limit(2)) assertEquals(cursor.size(), 2) - cursor = find().sort("a", SortOrder.Descending, NullOrder.First) + cursor = find(orderBy("a", SortOrder.Descending)) assertEquals(cursor.size(), 5) assertEquals(cursor.last()["a"], 1) - cursor = find().sort("a", SortOrder.Descending).skipLimit(0, 2) + cursor = find(orderBy("a", SortOrder.Descending).skip(0).limit(2)) assertEquals(cursor.size(), 2) assertEquals(cursor.last()["a"], 4) } @@ -169,7 +172,7 @@ class NitriteTest : BaseTest() { val repository = db?.getRepository()!! repository.insert(first) - repository.createIndex("ob1", IndexOptions.indexOptions(IndexType.Fulltext)); + repository.createIndex(indexOptions(IndexType.FULL_TEXT), "ob1"); var found = repository.find("ob1" text "value1") assertFalse(found.isEmpty) @@ -188,7 +191,7 @@ interface MyInterface { val id: UUID } -@Indices(value = [(Index(value = "name", type = IndexType.NonUnique))]) +@Indices(value = [(Index(value = ["name"], type = IndexType.NON_UNIQUE))]) abstract class SomeAbsClass( @Id override val id: UUID = UUID.randomUUID(), open val name: String = "abcd" @@ -215,7 +218,7 @@ data class CaObject( val name: String ) -@Indices(value = [(Index(value = "time", type = IndexType.Unique))]) +@Indices(value = [(Index(value = ["time"], type = IndexType.UNIQUE))]) data class ClassWithLocalDateTime( val name: String, val time: LocalDateTime diff --git a/potassium-nitrite/src/test/kotlin/org/dizitart/kno2/ObjectFilterTest.kt b/potassium-nitrite/src/test/kotlin/org/dizitart/kno2/ObjectFilterTest.kt index 4409e4cac..0aa0b6990 100644 --- a/potassium-nitrite/src/test/kotlin/org/dizitart/kno2/ObjectFilterTest.kt +++ b/potassium-nitrite/src/test/kotlin/org/dizitart/kno2/ObjectFilterTest.kt @@ -321,7 +321,7 @@ class ObjectFilterTest : BaseTest() { } } -@Indices(Index(value = "text", type = IndexType.Fulltext)) +@Indices(Index(value = ["text"], type = IndexType.FULL_TEXT)) data class TestData(@Id val id: Int, val text: String, val list: List = listOf()) class ListData(val name: String, val score: Int) @@ -331,7 +331,7 @@ data class SimpleObject( val value: Boolean ) -@Index(value = "geometry", type = SpatialIndexer.SpatialIndex) +@Index(value = ["geometry"], type = SpatialIndexer.SPATIAL_INDEX) data class SpatialData( @Id val id: Long, val geometry: Geometry diff --git a/rx-nitrite/src/main/java/org/dizitart/no2/rx/FlowableCursor.java b/rx-nitrite/src/main/java/org/dizitart/no2/rx/FlowableCursor.java index 52f8cbb5a..e009b3a3a 100644 --- a/rx-nitrite/src/main/java/org/dizitart/no2/rx/FlowableCursor.java +++ b/rx-nitrite/src/main/java/org/dizitart/no2/rx/FlowableCursor.java @@ -18,7 +18,6 @@ import io.reactivex.internal.functions.ObjectHelper; import org.dizitart.no2.common.Lookup; -import org.dizitart.no2.common.NullOrder; import org.dizitart.no2.common.RecordStream; import org.dizitart.no2.common.SortOrder; import org.dizitart.no2.repository.Cursor; @@ -29,7 +28,7 @@ /** * @author Anindya Chatterjee */ -public final class FlowableCursor extends FlowableReadableStream { +public final class FlowableCursor extends FlowableRecordStream { private final Callable> supplier; @@ -88,18 +87,18 @@ public FlowableCursor limit(int offset, int size) { return new FlowableCursor<>(sortSupplier); } - public

    FlowableReadableStream

    project(Class

    projectionType) { + public

    FlowableRecordStream

    project(Class

    projectionType) { Callable> projectionSupplier = () -> { Cursor cursor = ObjectHelper.requireNonNull(supplier.call(), "The supplier supplied is null"); return cursor.project(projectionType); }; - return FlowableReadableStream.create(projectionSupplier); + return FlowableRecordStream.create(projectionSupplier); } - public FlowableReadableStream join(FlowableCursor foreignCursor, Lookup lookup, - Class type) { + public FlowableRecordStream join(FlowableCursor foreignCursor, Lookup lookup, + Class type) { Callable> joinSupplier = () -> { Cursor cursor = ObjectHelper.requireNonNull(supplier.call(), "The supplier supplied is null"); @@ -109,6 +108,6 @@ public FlowableReadableStream join(FlowableCursor { +public final class FlowableDocumentCursor extends FlowableRecordStream { private final Callable supplier; @@ -89,16 +88,16 @@ public FlowableDocumentCursor limit(int offset, int size) { return new FlowableDocumentCursor(sortSupplier); } - public FlowableReadableStream project(Document projection) { + public FlowableRecordStream project(Document projection) { Callable> projectionSupplier = () -> { DocumentCursor documentCursor = ObjectHelper.requireNonNull(supplier.call(), "The supplier supplied is null"); return documentCursor.project(projection); }; - return FlowableReadableStream.create(projectionSupplier); + return FlowableRecordStream.create(projectionSupplier); } - public FlowableReadableStream join(FlowableDocumentCursor foreignCursor, Lookup lookup) { + public FlowableRecordStream join(FlowableDocumentCursor foreignCursor, Lookup lookup) { Callable> joinSupplier = () -> { DocumentCursor documentCursor = ObjectHelper.requireNonNull(supplier.call(), "The supplier supplied is null"); @@ -108,6 +107,6 @@ public FlowableReadableStream join(FlowableDocumentCursor foreignCurso return documentCursor.join(foreignDocumentCursor, lookup); }; - return FlowableReadableStream.create(joinSupplier); + return FlowableRecordStream.create(joinSupplier); } } diff --git a/rx-nitrite/src/main/java/org/dizitart/no2/rx/FlowableReadableStream.java b/rx-nitrite/src/main/java/org/dizitart/no2/rx/FlowableReadableStream.java deleted file mode 100644 index 70da16f9c..000000000 --- a/rx-nitrite/src/main/java/org/dizitart/no2/rx/FlowableReadableStream.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2017-2020. Nitrite author or authors. - * - * Licensed 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.dizitart.no2.rx; - -import io.reactivex.Maybe; -import io.reactivex.Single; -import io.reactivex.internal.functions.ObjectHelper; -import org.dizitart.no2.common.RecordStream; - -import java.util.concurrent.Callable; - -/** - * @author Anindya Chatterjee - */ -public abstract class FlowableReadableStream extends FlowableIterable { - - private final Callable> supplier; - - FlowableReadableStream(Callable> supplier) { - super(supplier); - this.supplier = supplier; - } - - static FlowableReadableStream create(Callable> supplier) { - return new FlowableReadableStream(supplier) { - }; - } - - public Single size() { - return Single.fromCallable(() -> { - RecordStream recordIterable = ObjectHelper.requireNonNull(supplier.call(), - "The supplier supplied is null"); - return recordIterable.size(); - }); - } - - public Maybe firstOrNull() { - return this.firstElement(); - } -} diff --git a/rx-nitrite/src/main/java/org/dizitart/no2/rx/FlowableRecordStream.java b/rx-nitrite/src/main/java/org/dizitart/no2/rx/FlowableRecordStream.java new file mode 100644 index 000000000..057324ece --- /dev/null +++ b/rx-nitrite/src/main/java/org/dizitart/no2/rx/FlowableRecordStream.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017-2020. Nitrite author or authors. + * + * Licensed 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.dizitart.no2.rx; + +import io.reactivex.Maybe; +import io.reactivex.Single; +import io.reactivex.internal.functions.ObjectHelper; +import org.dizitart.no2.common.RecordStream; + +import java.util.concurrent.Callable; + +/** + * @author Anindya Chatterjee + */ +public abstract class FlowableRecordStream extends FlowableIterable { + + private final Callable> supplier; + + FlowableRecordStream(Callable> supplier) { + super(supplier); + this.supplier = supplier; + } + + static FlowableRecordStream create(Callable> supplier) { + return new FlowableRecordStream(supplier) { + }; + } + + public Single size() { + return Single.fromCallable(() -> { + RecordStream recordIterable = ObjectHelper.requireNonNull(supplier.call(), + "The supplier supplied is null"); + return recordIterable.size(); + }); + } + + public Maybe firstOrNull() { + return this.firstElement(); + } +} diff --git a/rx-nitrite/src/main/java/org/dizitart/no2/rx/RxNitriteCollectionImpl.java b/rx-nitrite/src/main/java/org/dizitart/no2/rx/RxNitriteCollectionImpl.java index 9e4448887..f03ee8abc 100644 --- a/rx-nitrite/src/main/java/org/dizitart/no2/rx/RxNitriteCollectionImpl.java +++ b/rx-nitrite/src/main/java/org/dizitart/no2/rx/RxNitriteCollectionImpl.java @@ -28,7 +28,7 @@ import org.dizitart.no2.collection.events.EventType; import org.dizitart.no2.collection.meta.Attributes; import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexEntry; +import org.dizitart.no2.index.IndexDescriptor; import org.dizitart.no2.index.IndexOptions; import java.util.Collection; @@ -92,7 +92,7 @@ public Completable rebuildIndex(String field, boolean async) { } @Override - public Single> listIndices() { + public Single> listIndices() { return Single.fromCallable(nitriteCollection::listIndices); } diff --git a/rx-nitrite/src/main/java/org/dizitart/no2/rx/RxObjectRepositoryImpl.java b/rx-nitrite/src/main/java/org/dizitart/no2/rx/RxObjectRepositoryImpl.java index 9349efadc..fbff22faa 100644 --- a/rx-nitrite/src/main/java/org/dizitart/no2/rx/RxObjectRepositoryImpl.java +++ b/rx-nitrite/src/main/java/org/dizitart/no2/rx/RxObjectRepositoryImpl.java @@ -27,9 +27,9 @@ import org.dizitart.no2.collection.events.EventType; import org.dizitart.no2.collection.meta.Attributes; import org.dizitart.no2.filters.Filter; -import org.dizitart.no2.index.IndexEntry; +import org.dizitart.no2.index.IndexDescriptor; import org.dizitart.no2.index.IndexOptions; -import org.dizitart.no2.mapper.NitriteMapper; +import org.dizitart.no2.common.mapper.NitriteMapper; import org.dizitart.no2.repository.ObjectRepository; import java.util.Collection; @@ -123,7 +123,7 @@ public Completable rebuildIndex(String field, boolean async) { } @Override - public Single> listIndices() { + public Single> listIndices() { return Single.fromCallable(repository::listIndices); } diff --git a/rx-nitrite/src/main/java/org/dizitart/no2/rx/RxPersistentCollection.java b/rx-nitrite/src/main/java/org/dizitart/no2/rx/RxPersistentCollection.java index fbf6e0861..ec9ae381d 100644 --- a/rx-nitrite/src/main/java/org/dizitart/no2/rx/RxPersistentCollection.java +++ b/rx-nitrite/src/main/java/org/dizitart/no2/rx/RxPersistentCollection.java @@ -22,7 +22,7 @@ import org.dizitart.no2.collection.events.CollectionEventInfo; import org.dizitart.no2.collection.events.EventType; import org.dizitart.no2.collection.meta.Attributes; -import org.dizitart.no2.index.IndexEntry; +import org.dizitart.no2.index.IndexDescriptor; import org.dizitart.no2.index.IndexOptions; import java.util.Collection; @@ -35,7 +35,7 @@ public interface RxPersistentCollection { Completable rebuildIndex(String field, boolean async); - Single> listIndices(); + Single> listIndices(); Single hasIndex(String field); diff --git a/rx-nitrite/src/test/java/org/dizitart/no2/rx/RxBaseTest.java b/rx-nitrite/src/test/java/org/dizitart/no2/rx/RxBaseTest.java index 2ba03e12b..a95c448fd 100644 --- a/rx-nitrite/src/test/java/org/dizitart/no2/rx/RxBaseTest.java +++ b/rx-nitrite/src/test/java/org/dizitart/no2/rx/RxBaseTest.java @@ -23,8 +23,8 @@ import lombok.extern.slf4j.Slf4j; import org.dizitart.no2.Nitrite; import org.dizitart.no2.collection.Document; -import org.dizitart.no2.mapper.Mappable; -import org.dizitart.no2.mapper.NitriteMapper; +import org.dizitart.no2.common.mapper.Mappable; +import org.dizitart.no2.common.mapper.NitriteMapper; import org.dizitart.no2.mvstore.MVStoreModule; import org.dizitart.no2.repository.annotations.Id; import org.junit.Before; diff --git a/settings.gradle b/settings.gradle index ef83432f1..b988faedf 100644 --- a/settings.gradle +++ b/settings.gradle @@ -25,6 +25,5 @@ include 'nitrite-replication' include 'nitrite-support' include 'potassium-nitrite' include 'nitrite-rocksdb-adapter' -include 'nitrite-mapdb-adapter' include 'nitrite-bom'