diff --git a/README.md b/README.md index daa2f1ac..9bca03bc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# th2 common library (Java) (3.32.1) +# th2 common library (Java) (3.33.0) ## Usage @@ -288,6 +288,11 @@ dependencies { ## Release notes +### 3.33.0 + ++ Added ability to read dictionaries by aliases and as group of all available aliases ++ New methods for api: loadDictionary(String), getDictionaryAliases(), loadSingleDictionary() + ### 3.32.1 + Fixed: gRPC router didn't shut down underlying Netty's EventLoopGroup and ExecutorService diff --git a/gradle.properties b/gradle.properties index e112309e..3d838c7a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,7 @@ # limitations under the License. # -release_version=3.32.1 +release_version=3.33.0 description = 'th2 common library (Java)' diff --git a/src/main/java/com/exactpro/th2/common/schema/dictionary/DictionaryType.java b/src/main/java/com/exactpro/th2/common/schema/dictionary/DictionaryType.java index 37f09228..217128b1 100644 --- a/src/main/java/com/exactpro/th2/common/schema/dictionary/DictionaryType.java +++ b/src/main/java/com/exactpro/th2/common/schema/dictionary/DictionaryType.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2021 Exactpro (Exactpro Systems Limited) + * Copyright 2020-2022 Exactpro (Exactpro Systems Limited) * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/src/main/java/com/exactpro/th2/common/schema/factory/AbstractCommonFactory.java b/src/main/java/com/exactpro/th2/common/schema/factory/AbstractCommonFactory.java index 33333e10..b311b4a4 100644 --- a/src/main/java/com/exactpro/th2/common/schema/factory/AbstractCommonFactory.java +++ b/src/main/java/com/exactpro/th2/common/schema/factory/AbstractCommonFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2021 Exactpro (Exactpro Systems Limited) + * Copyright 2020-2022 Exactpro (Exactpro Systems Limited) * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -72,7 +72,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -95,17 +94,16 @@ import java.util.jar.Attributes.Name; import java.util.jar.JarFile; import java.util.jar.Manifest; -import java.util.stream.Collectors; import java.util.stream.StreamSupport; import static com.exactpro.cradle.cassandra.CassandraStorageSettings.DEFAULT_MAX_EVENT_BATCH_SIZE; import static com.exactpro.cradle.cassandra.CassandraStorageSettings.DEFAULT_MAX_MESSAGE_BATCH_SIZE; -import static com.exactpro.th2.common.schema.util.ArchiveUtils.getGzipBase64StringDecoder; import static java.util.Collections.emptyMap; import static java.util.Objects.requireNonNull; import static org.apache.commons.lang3.StringUtils.defaultIfBlank; /** + * * Class for load JSON schema configuration and create {@link GrpcRouter} and {@link MessageRouter} * * @see CommonFactory @@ -114,6 +112,7 @@ public abstract class AbstractCommonFactory implements AutoCloseable { protected static final String DEFAULT_CRADLE_INSTANCE_NAME = "infra"; protected static final String EXACTPRO_IMPLEMENTATION_VENDOR = "Exactpro Systems LLC"; + /** @deprecated please use {@link #LOG4J_PROPERTIES_DEFAULT_PATH} */ @Deprecated protected static final String LOG4J_PROPERTIES_DEFAULT_PATH_OLD = "/home/etc"; @@ -524,48 +523,41 @@ public T getCustomConfiguration(Class confClass) { } /** + * Read first and only one dictionary * @return Dictionary as {@link InputStream} + * @throws IllegalStateException if can not read dictionary or found more than one target + */ + public abstract InputStream loadSingleDictionary(); + + /** + * @return list of available dictionary aliases or an empty list * @throws IllegalStateException if can not read dictionary */ - public InputStream readDictionary() { - return readDictionary(DictionaryType.MAIN); - } + public abstract Set getDictionaryAliases(); /** - * @param dictionaryType desired type of dictionary + * @param alias name of dictionary * @return Dictionary as {@link InputStream} * @throws IllegalStateException if can not read dictionary */ - public InputStream readDictionary(DictionaryType dictionaryType) { - try { - List dictionaries = null; - Path dictionaryTypeDictionary = dictionaryType.getDictionary(getPathToDictionariesDir()); - if (Files.exists(dictionaryTypeDictionary) && Files.isDirectory(dictionaryTypeDictionary)) { - dictionaries = Files.list(dictionaryType.getDictionary(getPathToDictionariesDir())) - .filter(Files::isRegularFile) - .collect(Collectors.toList()); - } - - // Find with old format - if (dictionaries == null || dictionaries.isEmpty()) { - dictionaries = Files.list(getOldPathToDictionariesDir()) - .filter(path -> Files.isRegularFile(path) && path.getFileName().toString().contains(dictionaryType.name())) - .collect(Collectors.toList()); - } + public abstract InputStream loadDictionary(String alias); - if (dictionaries.isEmpty()) { - throw new IllegalStateException("No dictionary found with type '" + dictionaryType + "'"); - } else if (dictionaries.size() > 1) { - throw new IllegalStateException("Found several dictionaries satisfying the '" + dictionaryType + "' type"); - } - - var targetDictionary = dictionaries.get(0); + /** + * Read dictionary of {@link DictionaryType#MAIN} type + * @return Dictionary as {@link InputStream} + * @throws IllegalStateException if can not read dictionary + */ + @Deprecated(since = "3.33.0", forRemoval = true) + public abstract InputStream readDictionary(); - return new ByteArrayInputStream(getGzipBase64StringDecoder().decode(Files.readString(targetDictionary))); - } catch (IOException e) { - throw new IllegalStateException("Can not read dictionary", e); - } - } + /** + * @deprecated Dictionary types will be removed in future releases of infra, use alias instead + * @param dictionaryType desired type of dictionary + * @return Dictionary as {@link InputStream} + * @throws IllegalStateException if can not read dictionary + */ + @Deprecated(since = "3.33.0", forRemoval = true) + public abstract InputStream readDictionary(DictionaryType dictionaryType); /** * If root event does not exist, it creates root event with its name = box name and timestamp @@ -610,10 +602,17 @@ public String getRootEventId() { protected abstract Path getPathToCustomConfiguration(); /** - * @return Path to dictionary + * @return Path to dictionaries with type dir + */ + @Deprecated(since = "3.33.0", forRemoval = true) + protected abstract Path getPathToDictionaryTypesDir(); + + /** + * @return Path to dictionaries with alias dir */ - protected abstract Path getPathToDictionariesDir(); + protected abstract Path getPathToDictionaryAliasesDir(); + @Deprecated(since = "3.33.0", forRemoval = true) protected abstract Path getOldPathToDictionariesDir(); /** diff --git a/src/main/java/com/exactpro/th2/common/schema/factory/CommonFactory.java b/src/main/java/com/exactpro/th2/common/schema/factory/CommonFactory.java index edf56014..2f01a927 100644 --- a/src/main/java/com/exactpro/th2/common/schema/factory/CommonFactory.java +++ b/src/main/java/com/exactpro/th2/common/schema/factory/CommonFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2021 Exactpro (Exactpro Systems Limited) + * Copyright 2020-2022 Exactpro (Exactpro Systems Limited) * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -53,22 +53,29 @@ import org.apache.commons.cli.ParseException; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.io.FilenameUtils; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nullable; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import java.util.Base64; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import static com.exactpro.th2.common.schema.util.ArchiveUtils.getGzipBase64StringDecoder; import static java.util.Collections.emptyMap; import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNullElse; @@ -92,7 +99,10 @@ public class CommonFactory extends AbstractCommonFactory { private static final String CONNECTION_MANAGER_CONF_FILE_NAME = "mq_router.json"; private static final String CRADLE_NON_CONFIDENTIAL_FILE_NAME = "cradle_manager.json"; - private static final String DICTIONARY_DIR_NAME = "dictionary"; + /** @deprecated please use {@link #DICTIONARY_ALIAS_DIR_NAME} */ + @Deprecated + private static final String DICTIONARY_TYPE_DIR_NAME = "dictionary"; + private static final String DICTIONARY_ALIAS_DIR_NAME = "dictionaries"; private static final String RABBITMQ_SECRET_NAME = "rabbitmq"; private static final String CASSANDRA_SECRET_NAME = "cassandra"; @@ -105,7 +115,8 @@ public class CommonFactory extends AbstractCommonFactory { private static final String GENERATED_CONFIG_DIR_NAME = "generated_configs"; private final Path custom; - private final Path dictionariesDir; + private final Path dictionaryTypesDir; + private final Path dictionaryAliasesDir; private final Path oldDictionariesDir; private final ConfigurationManager configurationManager; @@ -117,14 +128,16 @@ protected CommonFactory(Class> messageRout Class> eventBatchRouterClass, Class grpcRouterClass, @Nullable Path custom, - @Nullable Path dictionariesDir, + @Nullable Path dictionaryTypesDir, + @Nullable Path dictionaryAliasesDir, @Nullable Path oldDictionariesDir, Map environmentVariables, ConfigurationManager configurationManager) { super(messageRouterParsedBatchClass, messageRouterRawBatchClass, messageRouterMessageGroupBatchClass, eventBatchRouterClass, grpcRouterClass, environmentVariables); this.custom = defaultPathIfNull(custom, CUSTOM_FILE_NAME); - this.dictionariesDir = defaultPathIfNull(dictionariesDir, DICTIONARY_DIR_NAME); + this.dictionaryTypesDir = defaultPathIfNull(dictionaryTypesDir, DICTIONARY_TYPE_DIR_NAME); + this.dictionaryAliasesDir = defaultPathIfNull(dictionaryAliasesDir, DICTIONARY_ALIAS_DIR_NAME); this.oldDictionariesDir = requireNonNullElse(oldDictionariesDir, CONFIG_DEFAULT_PATH); this.configurationManager = configurationManager; @@ -138,7 +151,8 @@ public CommonFactory(FactorySettings settings) { settings.getEventBatchRouterClass(), settings.getGrpcRouterClass(), settings.getCustom(), - settings.getDictionariesDir(), + settings.getDictionaryTypesDir(), + settings.getDictionaryAliasesDir(), settings.getOldDictionariesDir(), settings.getVariables(), createConfigurationManager(settings)); @@ -205,8 +219,13 @@ protected Path getPathToCustomConfiguration() { } @Override - protected Path getPathToDictionariesDir() { - return dictionariesDir; + protected Path getPathToDictionaryTypesDir() { + return dictionaryTypesDir; + } + + @Override + protected Path getPathToDictionaryAliasesDir() { + return dictionaryAliasesDir; } @Override @@ -340,8 +359,8 @@ public static CommonFactory createFromArguments(String... args) { settings.setPrometheus(calculatePath(cmd, prometheusConfigurationOption, configs, PROMETHEUS_FILE_NAME)); settings.setBoxConfiguration(calculatePath(cmd, boxConfigurationOption, configs, BOX_FILE_NAME)); settings.setCustom(calculatePath(cmd, customConfigurationOption, configs, CUSTOM_FILE_NAME)); - settings.setDictionariesDir(calculatePath(cmd, dictionariesDirOption, configs, DICTIONARY_DIR_NAME)); - + settings.setDictionaryTypesDir(calculatePath(cmd, dictionariesDirOption, configs, DICTIONARY_TYPE_DIR_NAME)); + settings.setDictionaryAliasesDir(calculatePath(cmd, dictionariesDirOption, configs, DICTIONARY_ALIAS_DIR_NAME)); String oldDictionariesDir = cmd.getOptionValue(dictionariesDirOption.getLongOpt()); settings.setOldDictionariesDir(oldDictionariesDir == null ? (configs == null ? CONFIG_DEFAULT_PATH : Path.of(configs)) : Path.of(oldDictionariesDir)); @@ -394,7 +413,9 @@ public static CommonFactory createFromKubernetes(String namespace, String boxNam Path configPath = Path.of(System.getProperty("user.dir"), GENERATED_CONFIG_DIR_NAME); - Path dictionaryPath = configPath.resolve(DICTIONARY_DIR_NAME); + Path dictionaryTypePath = configPath.resolve(DICTIONARY_TYPE_DIR_NAME); + Path dictionaryAliasPath = configPath.resolve(DICTIONARY_ALIAS_DIR_NAME); + Path boxConfigurationPath = configPath.resolve(BOX_FILE_NAME); FactorySettings settings = new FactorySettings(); @@ -459,7 +480,8 @@ public static CommonFactory createFromKubernetes(String namespace, String boxNam settings.setCustom(writeFile(configPath, CUSTOM_FILE_NAME, boxData)); settings.setBoxConfiguration(boxConfigurationPath); - settings.setDictionariesDir(dictionaryPath); + settings.setDictionaryTypesDir(dictionaryTypePath); + settings.setDictionaryAliasesDir(dictionaryAliasPath); String boxConfig = boxData.get(BOX_FILE_NAME); @@ -468,7 +490,7 @@ public static CommonFactory createFromKubernetes(String namespace, String boxNam else writeToJson(boxConfigurationPath, box); - writeDictionaries(boxName, configPath, dictionaryPath, dictionaries, configMaps.list()); + writeDictionaries(boxName, configPath, dictionaryTypePath, dictionaries, configMaps.list()); } return new CommonFactory(settings); @@ -478,6 +500,126 @@ public static CommonFactory createFromKubernetes(String namespace, String boxNam } } + @Override + public InputStream loadSingleDictionary() { + Path dictionaryFolder = getPathToDictionaryAliasesDir(); + try { + LOGGER.debug("Loading dictionary from folder: {}", dictionaryFolder); + List dictionaries = null; + if (Files.isDirectory(dictionaryFolder)) { + try (Stream files = Files.list(dictionaryFolder)) { + dictionaries = files.filter(Files::isRegularFile).collect(Collectors.toList()); + } + } + + if (dictionaries==null || dictionaries.isEmpty()) { + throw new IllegalStateException("No dictionary at path: " + dictionaryFolder.toAbsolutePath()); + } else if (dictionaries.size() > 1) { + throw new IllegalStateException("Found several dictionaries at path: " + dictionaryFolder.toAbsolutePath()); + } + + var targetDictionary = dictionaries.get(0); + + return new ByteArrayInputStream(getGzipBase64StringDecoder().decode(Files.readString(targetDictionary))); + } catch (IOException e) { + throw new IllegalStateException("Can not read dictionary from path: " + dictionaryFolder.toAbsolutePath(), e); + } + } + + @Override + public Set getDictionaryAliases() { + Path dictionaryFolder = getPathToDictionaryAliasesDir(); + try { + if (!Files.isDirectory(dictionaryFolder)) { + return Set.of(); + } + + try (Stream files = Files.list(dictionaryFolder)) { + return files + .filter(Files::isRegularFile) + .map(dictionary -> FilenameUtils.removeExtension(dictionary.getFileName().toString())) + .collect(Collectors.toSet()); + } + } catch (IOException e) { + throw new IllegalStateException("Can not get dictionaries aliases from path: " + dictionaryFolder.toAbsolutePath(), e); + } + } + + @Override + public InputStream loadDictionary(String alias) { + Path dictionaryFolder = getPathToDictionaryAliasesDir(); + try { + LOGGER.debug("Loading dictionary by alias ({}) from folder: {}", alias, dictionaryFolder); + List dictionaries = null; + + if (Files.isDirectory(dictionaryFolder)) { + try (Stream files = Files.list(dictionaryFolder)) { + dictionaries = files + .filter(Files::isRegularFile) + .filter(path -> FilenameUtils.removeExtension(path.getFileName().toString()).equalsIgnoreCase(alias)) + .collect(Collectors.toList()); + } + } + + if (dictionaries==null || dictionaries.isEmpty()) { + throw new IllegalStateException("No dictionary was found by alias '" + alias + "' at path: " + dictionaryFolder.toAbsolutePath()); + } else if (dictionaries.size() > 1) { + throw new IllegalStateException("Found several dictionaries by alias '" + alias + "' at path: " + dictionaryFolder.toAbsolutePath()); + } + + return new ByteArrayInputStream(getGzipBase64StringDecoder().decode(Files.readString(dictionaries.get(0)))); + } catch (IOException e) { + throw new IllegalStateException("Can not read dictionary '" + alias + "' from path: " + dictionaryFolder.toAbsolutePath(), e); + } + } + + @Override + public InputStream readDictionary() { + return readDictionary(DictionaryType.MAIN); + } + + @Override + public InputStream readDictionary(DictionaryType dictionaryType) { + try { + List dictionaries = null; + Path typeFolder = dictionaryType.getDictionary(getPathToDictionaryTypesDir()); + if (Files.isDirectory(typeFolder)) { + try (Stream files = Files.list(typeFolder)) { + dictionaries = files.filter(Files::isRegularFile) + .collect(Collectors.toList()); + } + } + + // Find with old format + Path oldFolder = getOldPathToDictionariesDir(); + if ((dictionaries == null || dictionaries.isEmpty()) && Files.isDirectory(oldFolder)) { + try (Stream files = Files.list(oldFolder)) { + dictionaries = files.filter(path -> Files.isRegularFile(path) && path.getFileName().toString().contains(dictionaryType.name())) + .collect(Collectors.toList()); + } + } + + Path dictionaryAliasFolder = getPathToDictionaryAliasesDir(); + if ((dictionaries == null || dictionaries.isEmpty()) && Files.isDirectory(dictionaryAliasFolder)) { + try (Stream files = Files.list(dictionaryAliasFolder)) { + dictionaries = files.filter(Files::isRegularFile).filter(path -> FilenameUtils.removeExtension(path.getFileName().toString()).equalsIgnoreCase(dictionaryType.name())).collect(Collectors.toList()); + } + } + + if (dictionaries == null || dictionaries.isEmpty()) { + throw new IllegalStateException("No dictionary found with type '" + dictionaryType + "'"); + } else if (dictionaries.size() > 1) { + throw new IllegalStateException("Found several dictionaries satisfying the '" + dictionaryType + "' type"); + } + + var targetDictionary = dictionaries.get(0); + + return new ByteArrayInputStream(getGzipBase64StringDecoder().decode(Files.readString(targetDictionary))); + } catch (IOException e) { + throw new IllegalStateException("Can not read dictionary", e); + } + } + private static Path writeFile(Path configPath, String fileName, Map configMap) throws IOException { Path file = configPath.resolve(fileName); writeFile(file, configMap.get(fileName)); @@ -523,8 +665,9 @@ private static void writeDictionaries(String boxName, Path oldDictionariesDir, P } String fileName = fileNameSet.stream().findFirst().orElse(null); - writeFile(dictionaryTypeDir.resolve(fileName), dictionaryConfigMap.getData().get(fileName)); - + Path dictionaryPath = dictionaryTypeDir.resolve(fileName); + writeFile(dictionaryPath, dictionaryConfigMap.getData().get(fileName)); + LOGGER.debug("Dictionary written in folder: " + dictionaryPath); break; } } diff --git a/src/main/kotlin/com/exactpro/th2/common/schema/factory/FactorySettings.kt b/src/main/kotlin/com/exactpro/th2/common/schema/factory/FactorySettings.kt index 8ae07513..1712e4f0 100644 --- a/src/main/kotlin/com/exactpro/th2/common/schema/factory/FactorySettings.kt +++ b/src/main/kotlin/com/exactpro/th2/common/schema/factory/FactorySettings.kt @@ -45,8 +45,9 @@ data class FactorySettings @JvmOverloads constructor( var prometheus: Path? = null, var boxConfiguration: Path? = null, var custom: Path? = null, - var dictionariesDir: Path? = null, - var oldDictionariesDir: Path? = null) { + @Deprecated("Will be removed in future releases") var dictionaryTypesDir: Path? = null, + var dictionaryAliasesDir: Path? = null, + @Deprecated("Will be removed in future releases") var oldDictionariesDir: Path? = null) { private val _variables: MutableMap = HashMap() val variables: Map = _variables diff --git a/src/test/kotlin/com/exactpro/th2/common/schema/TestDictionaryLoad.kt b/src/test/kotlin/com/exactpro/th2/common/schema/TestDictionaryLoad.kt index ea3b6950..76fae29f 100644 --- a/src/test/kotlin/com/exactpro/th2/common/schema/TestDictionaryLoad.kt +++ b/src/test/kotlin/com/exactpro/th2/common/schema/TestDictionaryLoad.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020-2021 Exactpro (Exactpro Systems Limited) + * Copyright 2020-2022 Exactpro (Exactpro Systems Limited) * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -17,7 +17,10 @@ package com.exactpro.th2.common.schema import com.exactpro.th2.common.schema.dictionary.DictionaryType import com.exactpro.th2.common.schema.factory.CommonFactory +import com.exactpro.th2.common.schema.factory.FactorySettings +import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test +import java.nio.file.Path class TestDictionaryLoad { @@ -39,4 +42,60 @@ class TestDictionaryLoad { } } + @Test + fun `test folder load dictionaries by alias`() { + val factory = CommonFactory.createFromArguments("-c", "src/test/resources/test_load_dictionaries") + + Assertions.assertDoesNotThrow { + factory.loadDictionary("test_alias_2").use { + assert(String(it.readAllBytes()) == "test file") + } + } + } + + @Test + fun `test folder load all dictionary aliases`() { + val factory = CommonFactory.createFromArguments("-c", "src/test/resources/test_load_dictionaries") + val expectedNames = listOf("main", "test_alias_1", "test_alias_2", "test_alias_3", "test_alias_4") + val names = factory.dictionaryAliases + Assertions.assertEquals(5, names.size) + Assertions.assertTrue(names.containsAll(expectedNames)) + } + + @Test + fun `test folder load single dictionary from folder with several`() { + val factory = CommonFactory.createFromArguments("-c", "src/test/resources/test_load_dictionaries") + + Assertions.assertThrows(IllegalStateException::class.java) { + factory.loadSingleDictionary() + } + } + + @Test + fun `test folder load single dictionary`() { + val customSettings = FactorySettings().apply { + prometheus = Path.of("src/test/resources/test_load_dictionaries/prometheus.json") + dictionaryAliasesDir = Path.of("src/test/resources/test_load_dictionaries/single_dictionary") + } + val customFactory = CommonFactory(customSettings) + + customFactory.loadSingleDictionary().use { + assert(String(it.readAllBytes()) == "test file") + } + } + + @Test + fun `test folder load single dictionary by type as alias`() { + val customSettings = FactorySettings().apply { + prometheus = Path.of("src/test/resources/test_load_dictionaries/prometheus.json") + dictionaryTypesDir = Path.of("..") + dictionaryAliasesDir = Path.of("src/test/resources/test_load_dictionaries/dictionaries") + } + val customFactory = CommonFactory(customSettings) + + customFactory.readDictionary().use { + assert(String(it.readAllBytes()) == "test file") + } + } + } \ No newline at end of file diff --git a/src/test/resources/test_load_dictionaries/dictionaries/main b/src/test/resources/test_load_dictionaries/dictionaries/main new file mode 100644 index 00000000..0f3ff093 --- /dev/null +++ b/src/test/resources/test_load_dictionaries/dictionaries/main @@ -0,0 +1 @@ +H4sIAAAAAAAAACtJLS5RSMvMSQUAwWtk8gkAAAA= \ No newline at end of file diff --git a/src/test/resources/test_load_dictionaries/dictionaries/test_alias_1.encoded b/src/test/resources/test_load_dictionaries/dictionaries/test_alias_1.encoded new file mode 100644 index 00000000..0f3ff093 --- /dev/null +++ b/src/test/resources/test_load_dictionaries/dictionaries/test_alias_1.encoded @@ -0,0 +1 @@ +H4sIAAAAAAAAACtJLS5RSMvMSQUAwWtk8gkAAAA= \ No newline at end of file diff --git a/src/test/resources/test_load_dictionaries/dictionaries/test_alias_2 b/src/test/resources/test_load_dictionaries/dictionaries/test_alias_2 new file mode 100644 index 00000000..0f3ff093 --- /dev/null +++ b/src/test/resources/test_load_dictionaries/dictionaries/test_alias_2 @@ -0,0 +1 @@ +H4sIAAAAAAAAACtJLS5RSMvMSQUAwWtk8gkAAAA= \ No newline at end of file diff --git a/src/test/resources/test_load_dictionaries/dictionaries/test_alias_3.encoded b/src/test/resources/test_load_dictionaries/dictionaries/test_alias_3.encoded new file mode 100644 index 00000000..0f3ff093 --- /dev/null +++ b/src/test/resources/test_load_dictionaries/dictionaries/test_alias_3.encoded @@ -0,0 +1 @@ +H4sIAAAAAAAAACtJLS5RSMvMSQUAwWtk8gkAAAA= \ No newline at end of file diff --git a/src/test/resources/test_load_dictionaries/dictionaries/test_alias_4 b/src/test/resources/test_load_dictionaries/dictionaries/test_alias_4 new file mode 100644 index 00000000..0f3ff093 --- /dev/null +++ b/src/test/resources/test_load_dictionaries/dictionaries/test_alias_4 @@ -0,0 +1 @@ +H4sIAAAAAAAAACtJLS5RSMvMSQUAwWtk8gkAAAA= \ No newline at end of file diff --git a/src/test/resources/test_load_dictionaries/single_dictionary/test_alias_1.encoded b/src/test/resources/test_load_dictionaries/single_dictionary/test_alias_1.encoded new file mode 100644 index 00000000..0f3ff093 --- /dev/null +++ b/src/test/resources/test_load_dictionaries/single_dictionary/test_alias_1.encoded @@ -0,0 +1 @@ +H4sIAAAAAAAAACtJLS5RSMvMSQUAwWtk8gkAAAA= \ No newline at end of file