AMashenkov commented on code in PR #6213: URL: https://github.com/apache/ignite-3/pull/6213#discussion_r2194726509
########## modules/runner/src/test/java/org/apache/ignite/internal/configuration/compatibility/framework/ConfigurationTreeComparatorSelfTest.java: ########## @@ -170,6 +173,207 @@ void deprecatedAnnotationCantBeRemoved() { assertIncompatible(root2, root1); } + /** + * Check {@link ConfigurationModule#deletedPrefixes()} functionality. + */ + @Test + void testDeleted() { + // Build previous version config tree. + ConfigNode root = new ConfigNode(null, Map.of(Attributes.NAME, "root"), List.of(), + EnumSet.of(Flags.IS_ROOT), Set.of()); + + ConfigNode singleProp = new ConfigNode(root, Map.of(Attributes.NAME, "property"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); + + ConfigNode legacyProp = new ConfigNode(root, Map.of(Attributes.NAME, "legacyProperty"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); + + ConfigNode compoundProp = new ConfigNode(root, Map.of(Attributes.NAME, "list"), List.of(), + EnumSet.of(Flags.IS_INTERNAL), Set.of()); + + ConfigNode firstMemberOfCompoundProp = new ConfigNode(compoundProp, Map.of(Attributes.NAME, "firstProperty"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); + ConfigNode secondMemberOfCompoundProp = new ConfigNode(compoundProp, Map.of(Attributes.NAME, "secondProperty"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); + + compoundProp.addChildNodes(firstMemberOfCompoundProp, secondMemberOfCompoundProp); + + root.addChildNodes(singleProp, legacyProp, compoundProp); + + List<ConfigNode> snapshotMetadata = List.of(root); + + // Build next version config tree. Some properties are marked as deleted. + root = new ConfigNode(null, Map.of(Attributes.NAME, "root"), List.of(), + EnumSet.of(Flags.IS_ROOT), Set.of()); + + singleProp = new ConfigNode(root, Map.of(Attributes.NAME, "property"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); + + compoundProp = new ConfigNode(root, Map.of(Attributes.NAME, "list"), List.of(), + EnumSet.of(Flags.IS_INTERNAL), Set.of()); + + root.addChildNodes(List.of(singleProp, compoundProp)); + + List<ConfigNode> currentMetadata = List.of(root); + + ConfigurationModule configModule = new ConfigurationModule() { + @Override + public ConfigurationType type() { + return ConfigurationType.LOCAL; + } + + @Override + public Collection<String> deletedPrefixes() { + return List.of("root.legacyProperty", "root.list.*"); + } + }; + + Set<ConfigurationModule> allModules = Set.of(configModule); + + assertCompatible(snapshotMetadata, currentMetadata, allModules); + + // missed deleted properties + configModule = new ConfigurationModule() { + @Override + public ConfigurationType type() { + return ConfigurationType.LOCAL; + } + + @Override + public Collection<String> deletedPrefixes() { + return List.of("root.legacyProperty_notExist", "root.list.*"); + } + }; + + allModules = Set.of(configModule); + + assertIncompatible(snapshotMetadata, currentMetadata, allModules); + } + + @Test + void testCompatibleRename() { + ConfigNode oldNode = new ConfigNode(null, Map.of(Attributes.NAME, "oldTestCount"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); + + ConfigNode newNode = new ConfigNode(null, Map.of(Attributes.NAME, "newTestCount"), + List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of("oldTestCount")); + + assertCompatible(oldNode, newNode); + + // Equal configs, still compatible + oldNode = new ConfigNode(null, Map.of(Attributes.NAME, "newTestCount"), + List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of("oldTestCount")); + + newNode = new ConfigNode(null, Map.of(Attributes.NAME, "newTestCount"), + List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of("oldTestCount")); + + assertCompatible(oldNode, newNode); + + // TODO: need to have a possibility to check compatibility between outdated (officially no more supported) version and current one. + // I.e. previous tree with filled deletedPrefixes and current without - need to be compatible too, decided to make it later. + } + + @Test + void testInCompatibleRename() { + ConfigNode oldNode1 = new ConfigNode(null, Map.of(Attributes.NAME, "oldTestCount"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); + + ConfigNode newNode1 = new ConfigNode(null, Map.of(Attributes.NAME, "newTestCount"), + List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of("oldTestCount_missed")); + + assertIncompatible(oldNode1, newNode1); + + // Different root names, not compatible + ConfigNode root1 = new ConfigNode(null, Map.of(Attributes.NAME, "root1"), List.of(), + EnumSet.of(Flags.IS_ROOT), Set.of()); + + ConfigNode root2 = new ConfigNode(null, Map.of(Attributes.NAME, "root2"), List.of(), + EnumSet.of(Flags.IS_ROOT), Set.of()); + + ConfigNode oldNode2 = new ConfigNode(root1, Map.of(Attributes.NAME, "oldTestCount"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); + + root1.addChildNodes(oldNode2); + + ConfigNode newNode2 = new ConfigNode(root2, Map.of(Attributes.NAME, "newTestCount"), + List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of("oldTestCount")); + + root2.addChildNodes(newNode2); + + assertIncompatible(oldNode1, newNode1); + } + + /** + * Test scenario. <br> + * config ver1 has property : prop1 <br> + * config ver2 has renamed property : prop1 -> prop2 <br> + * config ver3 has deleted property : prop1, prop2 <br> + * <br> + * Check config transitions are possible: ver1 -> ver2, ver1 -> ver3, ver2 -> ver3 + */ + @Test + void testDeleteAfterRename() { + ConfigNode root = new ConfigNode(null, Map.of(Attributes.NAME, "root"), List.of(), + EnumSet.of(Flags.IS_ROOT), Set.of()); + + ConfigNode node1Ver1 = new ConfigNode(root, Map.of(Attributes.NAME, "oldTestCount"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); + + ConfigNode node2Ver1 = new ConfigNode(root, Map.of(Attributes.NAME, "fixed"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); Review Comment: ```suggestion ``` ########## modules/runner/src/test/java/org/apache/ignite/internal/configuration/compatibility/framework/ConfigurationTreeComparatorSelfTest.java: ########## @@ -170,6 +173,207 @@ void deprecatedAnnotationCantBeRemoved() { assertIncompatible(root2, root1); } + /** + * Check {@link ConfigurationModule#deletedPrefixes()} functionality. + */ + @Test + void testDeleted() { + // Build previous version config tree. + ConfigNode root = new ConfigNode(null, Map.of(Attributes.NAME, "root"), List.of(), + EnumSet.of(Flags.IS_ROOT), Set.of()); + + ConfigNode singleProp = new ConfigNode(root, Map.of(Attributes.NAME, "property"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); + + ConfigNode legacyProp = new ConfigNode(root, Map.of(Attributes.NAME, "legacyProperty"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); + + ConfigNode compoundProp = new ConfigNode(root, Map.of(Attributes.NAME, "list"), List.of(), + EnumSet.of(Flags.IS_INTERNAL), Set.of()); + + ConfigNode firstMemberOfCompoundProp = new ConfigNode(compoundProp, Map.of(Attributes.NAME, "firstProperty"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); + ConfigNode secondMemberOfCompoundProp = new ConfigNode(compoundProp, Map.of(Attributes.NAME, "secondProperty"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); + + compoundProp.addChildNodes(firstMemberOfCompoundProp, secondMemberOfCompoundProp); + + root.addChildNodes(singleProp, legacyProp, compoundProp); + + List<ConfigNode> snapshotMetadata = List.of(root); + + // Build next version config tree. Some properties are marked as deleted. + root = new ConfigNode(null, Map.of(Attributes.NAME, "root"), List.of(), + EnumSet.of(Flags.IS_ROOT), Set.of()); + + singleProp = new ConfigNode(root, Map.of(Attributes.NAME, "property"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); + + compoundProp = new ConfigNode(root, Map.of(Attributes.NAME, "list"), List.of(), + EnumSet.of(Flags.IS_INTERNAL), Set.of()); + + root.addChildNodes(List.of(singleProp, compoundProp)); + + List<ConfigNode> currentMetadata = List.of(root); + + ConfigurationModule configModule = new ConfigurationModule() { + @Override + public ConfigurationType type() { + return ConfigurationType.LOCAL; + } + + @Override + public Collection<String> deletedPrefixes() { + return List.of("root.legacyProperty", "root.list.*"); + } + }; + + Set<ConfigurationModule> allModules = Set.of(configModule); + + assertCompatible(snapshotMetadata, currentMetadata, allModules); + + // missed deleted properties + configModule = new ConfigurationModule() { + @Override + public ConfigurationType type() { + return ConfigurationType.LOCAL; + } + + @Override + public Collection<String> deletedPrefixes() { + return List.of("root.legacyProperty_notExist", "root.list.*"); + } + }; + + allModules = Set.of(configModule); + + assertIncompatible(snapshotMetadata, currentMetadata, allModules); + } + + @Test + void testCompatibleRename() { + ConfigNode oldNode = new ConfigNode(null, Map.of(Attributes.NAME, "oldTestCount"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); + + ConfigNode newNode = new ConfigNode(null, Map.of(Attributes.NAME, "newTestCount"), + List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of("oldTestCount")); + + assertCompatible(oldNode, newNode); + + // Equal configs, still compatible + oldNode = new ConfigNode(null, Map.of(Attributes.NAME, "newTestCount"), + List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of("oldTestCount")); + + newNode = new ConfigNode(null, Map.of(Attributes.NAME, "newTestCount"), + List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of("oldTestCount")); + + assertCompatible(oldNode, newNode); + + // TODO: need to have a possibility to check compatibility between outdated (officially no more supported) version and current one. + // I.e. previous tree with filled deletedPrefixes and current without - need to be compatible too, decided to make it later. + } + + @Test + void testInCompatibleRename() { + ConfigNode oldNode1 = new ConfigNode(null, Map.of(Attributes.NAME, "oldTestCount"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); + + ConfigNode newNode1 = new ConfigNode(null, Map.of(Attributes.NAME, "newTestCount"), + List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of("oldTestCount_missed")); + + assertIncompatible(oldNode1, newNode1); + + // Different root names, not compatible + ConfigNode root1 = new ConfigNode(null, Map.of(Attributes.NAME, "root1"), List.of(), + EnumSet.of(Flags.IS_ROOT), Set.of()); + + ConfigNode root2 = new ConfigNode(null, Map.of(Attributes.NAME, "root2"), List.of(), + EnumSet.of(Flags.IS_ROOT), Set.of()); + + ConfigNode oldNode2 = new ConfigNode(root1, Map.of(Attributes.NAME, "oldTestCount"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); + + root1.addChildNodes(oldNode2); + + ConfigNode newNode2 = new ConfigNode(root2, Map.of(Attributes.NAME, "newTestCount"), + List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of("oldTestCount")); + + root2.addChildNodes(newNode2); + + assertIncompatible(oldNode1, newNode1); + } + + /** + * Test scenario. <br> + * config ver1 has property : prop1 <br> + * config ver2 has renamed property : prop1 -> prop2 <br> + * config ver3 has deleted property : prop1, prop2 <br> + * <br> + * Check config transitions are possible: ver1 -> ver2, ver1 -> ver3, ver2 -> ver3 + */ + @Test + void testDeleteAfterRename() { + ConfigNode root = new ConfigNode(null, Map.of(Attributes.NAME, "root"), List.of(), + EnumSet.of(Flags.IS_ROOT), Set.of()); + + ConfigNode node1Ver1 = new ConfigNode(root, Map.of(Attributes.NAME, "oldTestCount"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); + + ConfigNode node2Ver1 = new ConfigNode(root, Map.of(Attributes.NAME, "fixed"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); + + root.addChildNodes(node1Ver1, node2Ver1); + + List<ConfigNode> metadataVer1 = List.of(root); + + root = new ConfigNode(null, Map.of(Attributes.NAME, "root"), List.of(), + EnumSet.of(Flags.IS_ROOT), Set.of()); + + ConfigNode node1Ver2 = new ConfigNode(root, Map.of(Attributes.NAME, "newTestCount"), + List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of("oldTestCount")); + + ConfigNode node2Ver2 = new ConfigNode(root, Map.of(Attributes.NAME, "fixed"), List.of(), + EnumSet.of(Flags.IS_VALUE), Set.of()); Review Comment: ```suggestion ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: notifications-unsubscr...@ignite.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org