diff --git a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/AbstractJarVersionVerifier.java b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/AbstractJarVersionVerifier.java new file mode 100644 index 000000000..cf79a3843 --- /dev/null +++ b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/AbstractJarVersionVerifier.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.boot.compatibility; + +import org.springframework.core.env.Environment; + +import java.util.Collection; + +/** + * Abstract class for {@link AbstractSwitchableCompatibilityVerifier} to verify jar compatibility. + * + * @author huzijie + * @version AbstractJarVersionVerifier.java, v 0.1 2023年08月03日 5:14 PM huzijie Exp $ + */ +public abstract class AbstractJarVersionVerifier extends AbstractSwitchableCompatibilityVerifier { + + public AbstractJarVersionVerifier(Environment environment) { + super(environment); + } + + @Override + public CompatibilityPredicate compatibilityPredicate() { + return () -> { + Collection compatibilityPredicates = getJarCompatibilityPredicates(); + if (compatibilityPredicates == null) { + return true; + } + return compatibilityPredicates.stream().allMatch(CompatibilityPredicate::isCompatible); + }; + } + + @Override + public String errorDescription() { + return String.format("SOFABoot is not compatible with jar [%s] for current version.", + name()); + } + + @Override + public String action() { + return String.format( + "Change [%s] to appropriate version," + + "you can visit this doc [%s] and find an appropriate version," + + "If you want to disable this check, just set the property [%s=false].", + name(), doc(), this.enableKey); + } + + public abstract Collection getJarCompatibilityPredicates(); + + public abstract String name(); + + public abstract String doc(); +} diff --git a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/AbstractSwitchableCompatibilityVerifier.java b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/AbstractSwitchableCompatibilityVerifier.java new file mode 100644 index 000000000..a005ec28c --- /dev/null +++ b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/AbstractSwitchableCompatibilityVerifier.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.boot.compatibility; + +import org.springframework.core.env.Environment; + +/** + * Abstract class for {@link CompatibilityVerifier} to support switch. + * + * @author huzijie + * @version AbstractSwitchableCompatibilityVerifier.java, v 0.1 2023年08月03日 6:10 PM huzijie Exp $ + */ +public abstract class AbstractSwitchableCompatibilityVerifier implements CompatibilityVerifier { + + private static final String ENABLE_KEY_FORMAT = "sofa.boot.compatibility-verifier.%s.enabled"; + + protected final Environment environment; + + protected String enableKey; + + public AbstractSwitchableCompatibilityVerifier(Environment environment) { + this.environment = environment; + } + + @Override + public VerificationResult verify() { + this.enableKey = String.format(ENABLE_KEY_FORMAT, enableKey()); + if (!Boolean.parseBoolean(environment.getProperty(enableKey, "true"))) { + return VerificationResult.compatible(); + } + + CompatibilityPredicate compatibilityPredicate = compatibilityPredicate(); + boolean matches = compatibilityPredicate.isCompatible(); + if (matches) { + return VerificationResult.compatible(); + } + return VerificationResult.notCompatible(errorDescription(), action()); + } + + public abstract CompatibilityPredicate compatibilityPredicate(); + + public abstract String errorDescription(); + + public abstract String action(); + + public abstract String enableKey(); +} diff --git a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/CompatibilityNotMetException.java b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/CompatibilityNotMetException.java new file mode 100644 index 000000000..09bfbf693 --- /dev/null +++ b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/CompatibilityNotMetException.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.boot.compatibility; + +import java.util.Arrays; +import java.util.List; + +/** + * Exception for not compatibility met. + * + * @author huzijie + * @version CompatibilityNotMetException.java, v 0.1 2023年08月03日 4:40 PM huzijie Exp $ + */ +public class CompatibilityNotMetException extends RuntimeException { + + final List results; + + CompatibilityNotMetException(List results, String errorMessage) { + super("Compatibility checks have failed: " + errorMessage); + this.results = results; + } +} diff --git a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/CompatibilityPredicate.java b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/CompatibilityPredicate.java new file mode 100644 index 000000000..d5d43745b --- /dev/null +++ b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/CompatibilityPredicate.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.boot.compatibility; + +/** + * Interface for Predicate compatibility verify result, for form spring cloud. + * + * @author huzijie + * @version CompatibilityPredicate.java, v 0.1 2023年08月03日 4:35 PM huzijie Exp $ + */ +public interface CompatibilityPredicate { + + /** + * whether is compatible + * @return compatible result + */ + boolean isCompatible(); + +} diff --git a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/CompatibilityVerifier.java b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/CompatibilityVerifier.java new file mode 100644 index 000000000..6310da1ad --- /dev/null +++ b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/CompatibilityVerifier.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.boot.compatibility; + +/** + * Interface for compatibility verifier, for form spring cloud. + * + * @author huzijie + * @version CompatibilityVerifier.java, v 0.1 2023年08月03日 4:08 PM huzijie Exp $ + */ +public interface CompatibilityVerifier { + + /** + * verify compatibility + * @return verify result + */ + VerificationResult verify(); + +} diff --git a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/CompatibilityVerifierApplicationContextInitializer.java b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/CompatibilityVerifierApplicationContextInitializer.java new file mode 100644 index 000000000..4383261f0 --- /dev/null +++ b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/CompatibilityVerifierApplicationContextInitializer.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.boot.compatibility; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.annotation.AnnotationAwareOrderComparator; +import org.springframework.core.env.Environment; +import org.springframework.core.io.support.SpringFactoriesLoader; + +import java.util.List; + +/** + * Implements for {@link ApplicationContextInitializer} to verify compatibilities. + * + * @author huzijie + * @version CompatibilityVerifierApplicationContextInitializer.java, v 0.1 2023年08月03日 4:44 PM huzijie Exp $ + */ +public class CompatibilityVerifierApplicationContextInitializer + implements + ApplicationContextInitializer { + + public static final String COMPATIBILITY_VERIFIER_ENABLED = "sofa.boot.compatibility-verifier.enabled"; + + @Override + public void initialize(ConfigurableApplicationContext applicationContext) { + Environment environment = applicationContext.getEnvironment(); + if (!Boolean.parseBoolean(environment.getProperty(COMPATIBILITY_VERIFIER_ENABLED, "true"))) { + Logger logger = LoggerFactory.getLogger(CompatibilityVerifierApplicationContextInitializer.class); + logger.info("Skip SOFABoot compatibility Verifier"); + return; + } + + // Load all CompatibilityVerifier and verify. + CompositeCompatibilityVerifier compositeCompatibilityVerifier = new CompositeCompatibilityVerifier( + getCompatibilityVerifierInstances(environment)); + compositeCompatibilityVerifier.verifyCompatibilities(); + } + + private List getCompatibilityVerifierInstances(Environment environment) { + + SpringFactoriesLoader.ArgumentResolver argumentResolver = SpringFactoriesLoader.ArgumentResolver + .of(Environment.class, environment); + SpringFactoriesLoader springFactoriesLoader = SpringFactoriesLoader.forDefaultResourceLocation(); + // Use names and ensure unique to protect against duplicates + List instances = springFactoriesLoader.load( + CompatibilityVerifier.class, argumentResolver); + AnnotationAwareOrderComparator.sort(instances); + return instances; + } +} diff --git a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/CompositeCompatibilityVerifier.java b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/CompositeCompatibilityVerifier.java new file mode 100644 index 000000000..c555e775f --- /dev/null +++ b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/CompositeCompatibilityVerifier.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.boot.compatibility; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Composite compatibility verifier. + * + * @author huzijie + * @version CompositeCompatibilityVerifier.java, v 0.1 2023年08月03日 4:40 PM huzijie Exp $ + */ +public class CompositeCompatibilityVerifier { + + private final List verifiers; + + public CompositeCompatibilityVerifier(List verifiers) { + this.verifiers = verifiers; + } + + public void verifyCompatibilities() { + List errors = verifierErrors(); + if (errors.isEmpty()) { + return; + } + String errorMessage = errors.stream().map(VerificationResult::toErrorMessage).toList().toString(); + throw new CompatibilityNotMetException(errors, errorMessage); + } + + private List verifierErrors() { + List errors = new ArrayList<>(); + for (CompatibilityVerifier verifier : this.verifiers) { + VerificationResult result = verifier.verify(); + if (result.isNotCompatible()) { + errors.add(result); + } + } + return errors; + } +} diff --git a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/VerificationResult.java b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/VerificationResult.java new file mode 100644 index 000000000..45cf0db3a --- /dev/null +++ b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/compatibility/VerificationResult.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.boot.compatibility; + +import org.springframework.util.StringUtils; + +import java.util.Objects; + +/** + * Verification result. + * + * @author huzijie + * @version VerificationResult.java, v 0.1 2023年08月03日 4:08 PM huzijie Exp $ + */ +public class VerificationResult { + + private final String description; + + private final String action; + + // if OK + private VerificationResult() { + this.description = ""; + this.action = ""; + } + + // if not OK + private VerificationResult(String errorDescription, String action) { + this.description = errorDescription; + this.action = action; + } + + public static VerificationResult compatible() { + return new VerificationResult(); + } + + public static VerificationResult notCompatible(String errorDescription, String action) { + return new VerificationResult(errorDescription, action); + } + + public boolean isNotCompatible() { + return StringUtils.hasText(this.description) || StringUtils.hasText(this.action); + } + + public String toErrorMessage() { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("\n"); + stringBuilder.append("VerificationResult:"); + stringBuilder.append("\n"); + stringBuilder.append("—— description: "); + stringBuilder.append(description); + stringBuilder.append("\n"); + stringBuilder.append("—— action: "); + stringBuilder.append(action); + return stringBuilder.toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof VerificationResult that)) { + return false; + } + return description.equals(that.description) && action.equals(that.action); + } + + @Override + public int hashCode() { + return Objects.hash(description, action); + } +} diff --git a/sofa-boot-project/sofa-boot/src/main/resources/META-INF/spring.factories b/sofa-boot-project/sofa-boot/src/main/resources/META-INF/spring.factories index caf51cd3f..1aea1f8c4 100644 --- a/sofa-boot-project/sofa-boot/src/main/resources/META-INF/spring.factories +++ b/sofa-boot-project/sofa-boot/src/main/resources/META-INF/spring.factories @@ -12,3 +12,7 @@ org.springframework.context.ApplicationListener=com.alipay.sofa.boot.listener.Sp # Startup Listeners org.springframework.boot.SpringApplicationRunListener=\ com.alipay.sofa.boot.startup.StartupSpringApplicationRunListener + +# Initializers +org.springframework.context.ApplicationContextInitializer=\ + com.alipay.sofa.boot.compatibility.CompatibilityVerifierApplicationContextInitializer diff --git a/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/compatibility/AbstractJarVersionVerifierTests.java b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/compatibility/AbstractJarVersionVerifierTests.java new file mode 100644 index 000000000..f1fd7a531 --- /dev/null +++ b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/compatibility/AbstractJarVersionVerifierTests.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.boot.compatibility; + +import org.junit.jupiter.api.Test; +import org.springframework.core.env.Environment; +import org.springframework.mock.env.MockEnvironment; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author huzijie + * @version AbstractJarVersionVerifierTests.java, v 0.1 2023年08月07日 12:07 PM huzijie Exp $ + */ +public class AbstractJarVersionVerifierTests { + + private final MockEnvironment mockEnvironment = new MockEnvironment(); + + @Test + public void testJar() { + TestJarVersionVerifier verifier = new TestJarVersionVerifier(mockEnvironment); + assertThat(verifier.verify().isNotCompatible()).isTrue(); + } + + public static class TestJarVersionVerifier extends AbstractJarVersionVerifier { + + public TestJarVersionVerifier(Environment environment) { + super(environment); + } + + @Override + public Collection getJarCompatibilityPredicates() { + List list = new ArrayList<>(); + list.add(() -> false); + list.add(() -> true); + return list; + } + + @Override + public String name() { + return "test jar"; + } + + @Override + public String doc() { + return "test doc"; + } + + @Override + public String enableKey() { + return "test"; + } + } +} diff --git a/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/compatibility/AbstractSwitchableCompatibilityVerifierTests.java b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/compatibility/AbstractSwitchableCompatibilityVerifierTests.java new file mode 100644 index 000000000..7a289ea84 --- /dev/null +++ b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/compatibility/AbstractSwitchableCompatibilityVerifierTests.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.boot.compatibility; + +import org.junit.jupiter.api.Test; +import org.springframework.core.env.Environment; +import org.springframework.mock.env.MockEnvironment; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author huzijie + * @version AbstractSwitchableCompatibilityVerifierTests.java, v 0.1 2023年08月07日 11:56 AM huzijie Exp $ + */ +public class AbstractSwitchableCompatibilityVerifierTests { + + private final MockEnvironment mockEnvironment = new MockEnvironment(); + + @Test + public void enableKey() { + mockEnvironment.setProperty("sofa.boot.compatibility-verifier.test.enabled", "true"); + TestSwitchableCompatibilityVerifier verifier = new TestSwitchableCompatibilityVerifier( + mockEnvironment); + assertThat(verifier.verify().isNotCompatible()).isTrue(); + } + + @Test + public void disableKey() { + mockEnvironment.setProperty("sofa.boot.compatibility-verifier.test.enabled", "false"); + TestSwitchableCompatibilityVerifier verifier = new TestSwitchableCompatibilityVerifier( + mockEnvironment); + assertThat(verifier.verify().isNotCompatible()).isFalse(); + } + + public static class TestSwitchableCompatibilityVerifier extends + AbstractSwitchableCompatibilityVerifier { + + public TestSwitchableCompatibilityVerifier(Environment environment) { + super(environment); + } + + @Override + public CompatibilityPredicate compatibilityPredicate() { + return () -> false; + } + + @Override + public String errorDescription() { + return "adad"; + } + + @Override + public String action() { + return "dad"; + } + + @Override + public String enableKey() { + return "test"; + } + } +} diff --git a/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/compatibility/CompatibilityVerifierApplicationContextInitializerTests.java b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/compatibility/CompatibilityVerifierApplicationContextInitializerTests.java new file mode 100644 index 000000000..11080e64f --- /dev/null +++ b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/compatibility/CompatibilityVerifierApplicationContextInitializerTests.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.boot.compatibility; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.context.support.GenericXmlApplicationContext; +import org.springframework.mock.env.MockEnvironment; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +/** + * @author huzijie + * @version CompatibilityVerifierApplicationContextInitializerTests.java, v 0.1 2023年08月07日 12:11 PM huzijie Exp $ + */ +public class CompatibilityVerifierApplicationContextInitializerTests { + + private final MockEnvironment mockEnvironment = new MockEnvironment(); + + private final GenericApplicationContext applicationContext = new GenericXmlApplicationContext(); + + @BeforeEach + public void setUp() { + TestCompatibilityVerifier.invoked = false; + applicationContext.setEnvironment(mockEnvironment); + mockEnvironment.setProperty("enable.test.compatibility", "true"); + } + + @Test + public void enableKey() { + CompatibilityVerifierApplicationContextInitializer initializer = new CompatibilityVerifierApplicationContextInitializer(); + assertThatThrownBy(() -> initializer.initialize(applicationContext)) + .isInstanceOf(CompatibilityNotMetException.class) + .hasMessageContaining("description: test error") + .hasMessageContaining("action: test action"); + assertThat(TestCompatibilityVerifier.invoked).isTrue(); + } + + @Test + public void disableKey() { + mockEnvironment.setProperty("sofa.boot.compatibility-verifier.enabled", "false"); + CompatibilityVerifierApplicationContextInitializer initializer = new CompatibilityVerifierApplicationContextInitializer(); + initializer.initialize(applicationContext); + + assertThat(TestCompatibilityVerifier.invoked).isFalse(); + } + + @AfterEach + public void clear() { + TestCompatibilityVerifier.invoked = false; + } +} diff --git a/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/compatibility/CompositeCompatibilityVerifierTests.java b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/compatibility/CompositeCompatibilityVerifierTests.java new file mode 100644 index 000000000..720460072 --- /dev/null +++ b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/compatibility/CompositeCompatibilityVerifierTests.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.boot.compatibility; + +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +/** + * @author huzijie + * @version CompositeCompatibilityVerifierTests.java, v 0.1 2023年08月07日 12:00 PM huzijie Exp $ + */ +public class CompositeCompatibilityVerifierTests { + + @Test + public void empty() { + CompositeCompatibilityVerifier verifier = new CompositeCompatibilityVerifier( + new ArrayList<>()); + verifier.verifyCompatibilities(); + } + + @Test + public void pass() { + CompatibilityVerifier compatibilityVerifier = VerificationResult::compatible; + List verifiers = new ArrayList<>(); + verifiers.add(compatibilityVerifier); + CompositeCompatibilityVerifier verifier = new CompositeCompatibilityVerifier(verifiers); + verifier.verifyCompatibilities(); + } + + @Test + public void notPass() { + CompatibilityVerifier compatibilityVerifier = () -> VerificationResult.notCompatible("verify error", "do action"); + List verifiers = new ArrayList<>(); + verifiers.add(compatibilityVerifier); + CompositeCompatibilityVerifier verifier = new CompositeCompatibilityVerifier(verifiers); + assertThatThrownBy(verifier::verifyCompatibilities).isInstanceOf(CompatibilityNotMetException.class) + .hasMessageContaining("description: verify error") + .hasMessageContaining("action: do action"); + } +} diff --git a/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/compatibility/TestCompatibilityVerifier.java b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/compatibility/TestCompatibilityVerifier.java new file mode 100644 index 000000000..fca37a3dd --- /dev/null +++ b/sofa-boot-project/sofa-boot/src/test/java/com/alipay/sofa/boot/compatibility/TestCompatibilityVerifier.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.boot.compatibility; + +import org.springframework.core.env.Environment; +import org.springframework.util.Assert; + +/** + * @author huzijie + * @version TestCompatibilityVerifier.java, v 0.1 2023年08月07日 12:19 PM huzijie Exp $ + */ +public class TestCompatibilityVerifier implements CompatibilityVerifier { + + public static boolean invoked = false; + + private final Environment environment; + + public TestCompatibilityVerifier(Environment environment) { + this.environment = environment; + } + + @Override + public VerificationResult verify() { + Assert.notNull(environment, "environment must not null"); + invoked = true; + if (!environment.containsProperty("enable.test.compatibility")) { + return VerificationResult.compatible(); + } + return VerificationResult.notCompatible("test error", "test action"); + } +} diff --git a/sofa-boot-project/sofa-boot/src/test/resources/META-INF/spring.factories b/sofa-boot-project/sofa-boot/src/test/resources/META-INF/spring.factories index 3fba321f2..5f154d285 100644 --- a/sofa-boot-project/sofa-boot/src/test/resources/META-INF/spring.factories +++ b/sofa-boot-project/sofa-boot/src/test/resources/META-INF/spring.factories @@ -1,4 +1,7 @@ com.alipay.sofa.boot.spring.namespace.spi.SofaBootTagNameSupport=\ com.alipay.sofa.boot.spring.namespace.TestBeanDefinitionDecorator,\ com.alipay.sofa.boot.spring.namespace.TestBeanDefinitionParser,\ - com.alipay.sofa.boot.spring.namespace.TestNormalBean \ No newline at end of file + com.alipay.sofa.boot.spring.namespace.TestNormalBean + +com.alipay.sofa.boot.compatibility.CompatibilityVerifier=\ + com.alipay.sofa.boot.compatibility.TestCompatibilityVerifier \ No newline at end of file