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 */ 014 015package de.softwareforge.testing.postgres.junit5; 016 017import static com.google.common.base.Preconditions.checkNotNull; 018import static java.lang.String.format; 019 020import de.softwareforge.testing.postgres.embedded.EmbeddedPostgres; 021 022import java.io.IOException; 023import java.util.List; 024 025import com.google.auto.value.AutoValue; 026import com.google.common.base.Joiner; 027import com.google.common.base.Splitter; 028import com.google.common.collect.ComparisonChain; 029import org.junit.jupiter.api.extension.ConditionEvaluationResult; 030import org.junit.jupiter.api.extension.ExecutionCondition; 031import org.junit.jupiter.api.extension.ExtensionContext; 032import org.junit.platform.commons.support.AnnotationSupport; 033 034/** 035 * {@link ExecutionCondition} for {@link RequirePostgresVersion}. 036 * 037 * @see RequirePostgresVersion 038 * @since 4.1 039 */ 040public final class PostgresVersionCondition implements ExecutionCondition { 041 042 @Override 043 public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { 044 return AnnotationSupport.findAnnotation(context.getElement(), RequirePostgresVersion.class) 045 .map(this::checkPostgresVersion) 046 .orElse(ConditionEvaluationResult.enabled("No version annotation found")); 047 048 } 049 050 private ConditionEvaluationResult checkPostgresVersion(RequirePostgresVersion requirePostgresVersion) { 051 Version atLeastVersion = Version.valueOf(requirePostgresVersion.atLeast()); 052 Version lessThanVersion = Version.valueOf(requirePostgresVersion.lessThan()); 053 054 if (atLeastVersion.ignore() && lessThanVersion.ignore()) { 055 return ConditionEvaluationResult.enabled("No PostgreSQL version range set"); 056 } 057 058 try (EmbeddedPostgres pg = EmbeddedPostgres.forVersionCheck()) { 059 Version postgresVersion = Version.valueOf(pg.getPostgresVersion()); 060 061 if (!atLeastVersion.ignore() && postgresVersion.compareTo(atLeastVersion) < 0) { 062 return ConditionEvaluationResult.disabled( 063 format("Located PostgreSQL version is %s, at least version %s is required", postgresVersion, atLeastVersion)); 064 } 065 066 if (!lessThanVersion.ignore() && lessThanVersion.compareTo(postgresVersion) < 0) { 067 return ConditionEvaluationResult.disabled( 068 format("Located PostgreSQL version is %s, must be less than %s", postgresVersion, lessThanVersion)); 069 } 070 071 return ConditionEvaluationResult.enabled( 072 format("Located PostgreSQL version is %s, version range is %s - %s", postgresVersion, atLeastVersion, lessThanVersion)); 073 074 } catch (IOException e) { 075 return ConditionEvaluationResult.disabled("IOException while checking postgres version", e.getMessage()); 076 } 077 } 078 079 @AutoValue 080 abstract static class Version implements Comparable<Version> { 081 082 abstract int major(); 083 084 abstract int minor(); 085 086 abstract int patch(); 087 088 private static Version valueOf(String value) { 089 checkNotNull(value, "value is null"); 090 091 List<String> values = Splitter.on('.').trimResults().splitToList(value); 092 return new AutoValue_PostgresVersionCondition_Version(parseValue(values, 0), 093 parseValue(values, 1), 094 parseValue(values, 2)); 095 } 096 097 private static int parseValue(List<String> values, int pos) { 098 if (values.size() > pos && !values.get(pos).isEmpty()) { 099 try { 100 return Integer.parseInt(values.get(pos)); 101 } catch (NumberFormatException e) { 102 return 0; 103 } 104 } else { 105 return 0; 106 } 107 } 108 109 private boolean ignore() { 110 return major() == 0 && minor() == 0 && patch() == 0; 111 } 112 113 @Override 114 public int compareTo(Version other) { 115 return ComparisonChain.start() 116 .compare(major(), other.major()) 117 .compare(minor(), other.minor()) 118 .compare(patch(), other.patch()) 119 .result(); 120 } 121 122 @Override 123 public String toString() { 124 if (ignore()) { 125 return ""; 126 } else { 127 return Joiner.on('.').join(major(), minor(), patch()); 128 } 129 } 130 } 131}