View Javadoc
1   /*
2    * Licensed under the Apache License, Version 2.0 (the "License");
3    * you may not use this file except in compliance with the License.
4    * You may obtain a copy of the License at
5    *
6    * http://www.apache.org/licenses/LICENSE-2.0
7    *
8    * Unless required by applicable law or agreed to in writing, software
9    * distributed under the License is distributed on an "AS IS" BASIS,
10   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11   * See the License for the specific language governing permissions and
12   * limitations under the License.
13   */
14  
15  package de.softwareforge.testing.postgres.junit5;
16  
17  import static com.google.common.base.Preconditions.checkNotNull;
18  import static java.lang.String.format;
19  
20  import de.softwareforge.testing.postgres.embedded.EmbeddedPostgres;
21  
22  import java.io.IOException;
23  import java.util.List;
24  
25  import com.google.auto.value.AutoValue;
26  import com.google.common.base.Joiner;
27  import com.google.common.base.Splitter;
28  import com.google.common.collect.ComparisonChain;
29  import org.junit.jupiter.api.extension.ConditionEvaluationResult;
30  import org.junit.jupiter.api.extension.ExecutionCondition;
31  import org.junit.jupiter.api.extension.ExtensionContext;
32  import org.junit.platform.commons.support.AnnotationSupport;
33  
34  /**
35   * {@link ExecutionCondition} for {@link RequirePostgresVersion}.
36   *
37   * @see RequirePostgresVersion
38   * @since 4.1
39   */
40  public final class PostgresVersionCondition implements ExecutionCondition {
41  
42      @Override
43      public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
44          return AnnotationSupport.findAnnotation(context.getElement(), RequirePostgresVersion.class)
45                  .map(this::checkPostgresVersion)
46                  .orElse(ConditionEvaluationResult.enabled("No version annotation found"));
47  
48      }
49  
50      private ConditionEvaluationResult checkPostgresVersion(RequirePostgresVersion requirePostgresVersion) {
51          Version atLeastVersion = Version.valueOf(requirePostgresVersion.atLeast());
52          Version lessThanVersion = Version.valueOf(requirePostgresVersion.lessThan());
53  
54          if (atLeastVersion.ignore() && lessThanVersion.ignore()) {
55              return ConditionEvaluationResult.enabled("No PostgreSQL version range set");
56          }
57  
58          try (EmbeddedPostgres pg = EmbeddedPostgres.forVersionCheck()) {
59              Version postgresVersion = Version.valueOf(pg.getPostgresVersion());
60  
61              if (!atLeastVersion.ignore() && postgresVersion.compareTo(atLeastVersion) < 0) {
62                  return ConditionEvaluationResult.disabled(
63                          format("Located PostgreSQL version is %s, at least version %s is required", postgresVersion, atLeastVersion));
64              }
65  
66              if (!lessThanVersion.ignore() && lessThanVersion.compareTo(postgresVersion) < 0) {
67                  return ConditionEvaluationResult.disabled(
68                          format("Located PostgreSQL version is %s, must be less than %s", postgresVersion, lessThanVersion));
69              }
70  
71              return ConditionEvaluationResult.enabled(
72                      format("Located PostgreSQL version is %s, version range is %s - %s", postgresVersion, atLeastVersion, lessThanVersion));
73  
74          } catch (IOException e) {
75              return ConditionEvaluationResult.disabled("IOException while checking postgres version", e.getMessage());
76          }
77      }
78  
79      @AutoValue
80      abstract static class Version implements Comparable<Version> {
81  
82          abstract int major();
83  
84          abstract int minor();
85  
86          abstract int patch();
87  
88          private static Version valueOf(String value) {
89              checkNotNull(value, "value is null");
90  
91              List<String> values = Splitter.on('.').trimResults().splitToList(value);
92              return new AutoValue_PostgresVersionCondition_Version(parseValue(values, 0),
93                      parseValue(values, 1),
94                      parseValue(values, 2));
95          }
96  
97          private static int parseValue(List<String> values, int pos) {
98              if (values.size() > pos && !values.get(pos).isEmpty()) {
99                  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 }