001/* 002 * Licensed under the Apache License, Version 2.0 (the "License"); 003 * you may not use this file except in compliance with the License. 004 * You may obtain a copy of the License at 005 * 006 * http://www.apache.org/licenses/LICENSE-2.0 007 * 008 * Unless required by applicable law or agreed to in writing, software 009 * distributed under the License is distributed on an "AS IS" BASIS, 010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 011 * See the License for the specific language governing permissions and 012 * limitations under the License. 013 */ 014package de.softwareforge.testing.postgres.junit5; 015 016import static com.google.common.base.Preconditions.checkNotNull; 017import static java.lang.String.format; 018 019import de.softwareforge.testing.postgres.embedded.EmbeddedPostgres; 020 021import java.io.IOException; 022import java.util.List; 023 024import com.google.auto.value.AutoValue; 025import com.google.common.base.Joiner; 026import com.google.common.base.Splitter; 027import com.google.common.collect.ComparisonChain; 028import org.junit.jupiter.api.extension.ConditionEvaluationResult; 029import org.junit.jupiter.api.extension.ExecutionCondition; 030import org.junit.jupiter.api.extension.ExtensionContext; 031import org.junit.platform.commons.support.AnnotationSupport; 032 033/** 034 * {@link ExecutionCondition} for {@link RequirePostgresVersion}. 035 * 036 * @see RequirePostgresVersion 037 * @since 4.1 038 */ 039public final class PostgresVersionCondition implements ExecutionCondition { 040 041 @Override 042 public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { 043 return AnnotationSupport.findAnnotation(context.getElement(), RequirePostgresVersion.class) 044 .map(this::checkPostgresVersion) 045 .orElse(ConditionEvaluationResult.enabled("No version annotation found")); 046 047 } 048 049 private ConditionEvaluationResult checkPostgresVersion(RequirePostgresVersion requirePostgresVersion) { 050 Version atLeastVersion = Version.valueOf(requirePostgresVersion.atLeast()); 051 Version lessThanVersion = Version.valueOf(requirePostgresVersion.lessThan()); 052 053 if (atLeastVersion.ignore() && lessThanVersion.ignore()) { 054 return ConditionEvaluationResult.enabled("No PostgreSQL version range set"); 055 } 056 057 try (EmbeddedPostgres pg = EmbeddedPostgres.forVersionCheck()) { 058 Version postgresVersion = Version.valueOf(pg.getPostgresVersion()); 059 060 if (!atLeastVersion.ignore() && postgresVersion.compareTo(atLeastVersion) < 0) { 061 return ConditionEvaluationResult.disabled( 062 format("Located PostgreSQL version is %s, at least version %s is required", postgresVersion, atLeastVersion)); 063 } 064 065 if (!lessThanVersion.ignore() && lessThanVersion.compareTo(postgresVersion) < 0) { 066 return ConditionEvaluationResult.disabled( 067 format("Located PostgreSQL version is %s, must be less than %s", postgresVersion, lessThanVersion)); 068 } 069 070 return ConditionEvaluationResult.enabled( 071 format("Located PostgreSQL version is %s, version range is %s - %s", postgresVersion, atLeastVersion, lessThanVersion)); 072 073 } catch (IOException e) { 074 return ConditionEvaluationResult.disabled("IOException while checking postgres version", e.getMessage()); 075 } 076 } 077 078 @AutoValue 079 abstract static class Version implements Comparable<Version> { 080 081 abstract int major(); 082 083 abstract int minor(); 084 085 abstract int patch(); 086 087 private static Version valueOf(String value) { 088 checkNotNull(value, "value is null"); 089 090 List<String> values = Splitter.on('.').trimResults().splitToList(value); 091 return new AutoValue_PostgresVersionCondition_Version(parseValue(values, 0), 092 parseValue(values, 1), 093 parseValue(values, 2)); 094 } 095 096 private static int parseValue(List<String> values, int pos) { 097 if (values.size() > pos && !values.get(pos).isEmpty()) { 098 try { 099 return Integer.parseInt(values.get(pos)); 100 } catch (NumberFormatException e) { 101 return 0; 102 } 103 } else { 104 return 0; 105 } 106 } 107 108 private boolean ignore() { 109 return major() == 0 && minor() == 0 && patch() == 0; 110 } 111 112 @Override 113 public int compareTo(Version other) { 114 return ComparisonChain.start() 115 .compare(major(), other.major()) 116 .compare(minor(), other.minor()) 117 .compare(patch(), other.patch()) 118 .result(); 119 } 120 121 @Override 122 public String toString() { 123 if (ignore()) { 124 return ""; 125 } else { 126 return Joiner.on('.').join(major(), minor(), patch()); 127 } 128 } 129 } 130}