1919
2020package org .elasticsearch .test ;
2121
22- import org .elasticsearch .Version ;
23- import org .elasticsearch .common .Booleans ;
24- import org .elasticsearch .common .Nullable ;
25- import org .elasticsearch .common .collect .Tuple ;
26-
27- import java .lang .reflect .Field ;
28- import java .lang .reflect .Modifier ;
2922import java .util .ArrayList ;
30- import java .util .Arrays ;
3123import java .util .Collections ;
3224import java .util .List ;
25+ import java .util .Locale ;
26+ import java .util .Map ;
3327import java .util .Optional ;
3428import java .util .Random ;
29+ import java .util .SortedSet ;
30+ import java .util .TreeSet ;
3531import java .util .stream .Collectors ;
32+ import java .util .stream .Stream ;
3633
37- import static java .util .Collections .singletonList ;
38- import static java .util .Collections .unmodifiableList ;
34+ import org .elasticsearch .Version ;
35+ import org .elasticsearch .common .Nullable ;
36+ import org .elasticsearch .common .collect .Tuple ;
3937
4038/** Utilities for selecting versions in tests */
4139public class VersionUtils {
40+
4241 /**
4342 * Sort versions that have backwards compatibility guarantees from
4443 * those that don't. Doesn't actually check whether or not the versions
@@ -50,73 +49,65 @@ public class VersionUtils {
5049 * guarantees in v1 and versions without the guranteees in v2
5150 */
5251 static Tuple <List <Version >, List <Version >> resolveReleasedVersions (Version current , Class <?> versionClass ) {
53- List <Version > versions = Version .getDeclaredVersions (versionClass );
54-
55- Version last = versions .remove (versions .size () - 1 );
56- assert last .equals (current ) : "The highest version must be the current one "
57- + "but was [" + versions .get (versions .size () - 1 ) + "] and current was [" + current + "]" ;
58-
59- if (current .revision != 0 ) {
60- /* If we are in a stable branch there should be no unreleased version constants
61- * because we don't expect to release any new versions in older branches. If there
62- * are extra constants then gradle will yell about it. */
63- return new Tuple <>(unmodifiableList (versions ), singletonList (current ));
52+ // group versions into major version
53+ Map <Integer , List <Version >> majorVersions = Version .getDeclaredVersions (versionClass ).stream ()
54+ .collect (Collectors .groupingBy (v -> (int )v .major ));
55+ // this breaks b/c 5.x is still in version list but master doesn't care about it!
56+ //assert majorVersions.size() == 2;
57+ // TODO: remove oldVersions, we should only ever have 2 majors in Version
58+ List <Version > oldVersions = majorVersions .getOrDefault ((int )current .major - 2 , Collections .emptyList ());
59+ List <List <Version >> previousMajor = splitByMinor (majorVersions .get ((int )current .major - 1 ));
60+ List <List <Version >> currentMajor = splitByMinor (majorVersions .get ((int )current .major ));
61+
62+ List <Version > unreleasedVersions = new ArrayList <>();
63+ final List <List <Version >> stableVersions ;
64+ if (currentMajor .size () == 1 ) {
65+ // on master branch
66+ stableVersions = previousMajor ;
67+ // remove current
68+ moveLastToUnreleased (currentMajor , unreleasedVersions );
69+ } else {
70+ // on a stable or release branch, ie N.x
71+ stableVersions = currentMajor ;
72+ // remove the next maintenance bugfix
73+ moveLastToUnreleased (previousMajor , unreleasedVersions );
6474 }
6575
66- /* If we are on a patch release then we know that at least the version before the
67- * current one is unreleased. If it is released then gradle would be complaining. */
68- int unreleasedIndex = versions .size () - 1 ;
69- while (true ) {
70- if (unreleasedIndex < 0 ) {
71- throw new IllegalArgumentException ("Couldn't find first non-alpha release" );
72- }
73- /* We don't support backwards compatibility for alphas, betas, and rcs. But
74- * they were released so we add them to the released list. Usually this doesn't
75- * matter to consumers, but consumers that do care should filter non-release
76- * versions. */
77- if (versions .get (unreleasedIndex ).isRelease ()) {
78- break ;
76+ // remove next minor
77+ Version lastMinor = moveLastToUnreleased (stableVersions , unreleasedVersions );
78+ if (lastMinor .revision == 0 ) {
79+ if (stableVersions .get (stableVersions .size () - 1 ).size () == 1 ) {
80+ // a minor is being staged, which is also unreleased
81+ moveLastToUnreleased (stableVersions , unreleasedVersions );
7982 }
80- unreleasedIndex --;
83+ // remove the next bugfix
84+ moveLastToUnreleased (stableVersions , unreleasedVersions );
8185 }
8286
83- Version unreleased = versions .remove (unreleasedIndex );
84- if (unreleased .revision == 0 ) {
85- /*
86- * If the last unreleased version is itself a patch release then Gradle enforces that there is yet another unreleased version
87- * before that. However, we have to skip alpha/betas/RCs too (e.g., consider when the version constants are ..., 5.6.3, 5.6.4,
88- * 6.0.0-alpha1, ..., 6.0.0-rc1, 6.0.0-rc2, 6.0.0, 6.1.0 on the 6.x branch. In this case, we will have pruned 6.0.0 and 6.1.0 as
89- * unreleased versions, but we also need to prune 5.6.4. At this point though, unreleasedIndex will be pointing to 6.0.0-rc2, so
90- * we have to skip backwards until we find a non-alpha/beta/RC again. Then we can prune that version as an unreleased version
91- * too.
92- */
93- do {
94- unreleasedIndex --;
95- } while (versions .get (unreleasedIndex ).isRelease () == false );
96- Version earlierUnreleased = versions .remove (unreleasedIndex );
97-
98- // This earlierUnreleased is either the snapshot on the minor branch lower, or its possible its a staged release. If it is a
99- // staged release, remove it and return it in unreleased as well.
100- if (earlierUnreleased .revision == 0 ) {
101- unreleasedIndex --;
102- Version actualUnreleasedPreviousMinor = versions .remove (unreleasedIndex );
103- return new Tuple <>(unmodifiableList (versions ), unmodifiableList (Arrays .asList (actualUnreleasedPreviousMinor ,
104- earlierUnreleased , unreleased , current )));
105- }
87+ List <Version > releasedVersions = Stream .concat (oldVersions .stream (),
88+ Stream .concat (previousMajor .stream (), currentMajor .stream ()).flatMap (List ::stream ))
89+ .collect (Collectors .toList ());
90+ Collections .sort (unreleasedVersions ); // we add unreleased out of order, so need to sort here
91+ return new Tuple <>(Collections .unmodifiableList (releasedVersions ), Collections .unmodifiableList (unreleasedVersions ));
92+ }
10693
107- return new Tuple <>(unmodifiableList (versions ), unmodifiableList (Arrays .asList (earlierUnreleased , unreleased , current )));
108- } else if (unreleased .major == current .major ) {
109- // need to remove one more of the last major's minor set
110- do {
111- unreleasedIndex --;
112- } while (unreleasedIndex > 0 && versions .get (unreleasedIndex ).major == current .major );
113- if (unreleasedIndex > 0 ) {
114- // some of the test cases return very small lists, so its possible this is just the end of the list, if so, dont include it
115- Version earlierMajorsMinor = versions .remove (unreleasedIndex );
116- return new Tuple <>(unmodifiableList (versions ), unmodifiableList (Arrays .asList (earlierMajorsMinor , unreleased , current )));
117- }
94+ // split the given versions into sub lists grouped by minor version
95+ private static List <List <Version >> splitByMinor (List <Version > versions ) {
96+ Map <Integer , List <Version >> byMinor = versions .stream ().collect (Collectors .groupingBy (v -> (int )v .minor ));
97+ return byMinor .entrySet ().stream ().sorted (Map .Entry .comparingByKey ()).map (Map .Entry ::getValue ).collect (Collectors .toList ());
98+ }
99+
100+ // move the last version of the last minor in versions to the unreleased versions
101+ private static Version moveLastToUnreleased (List <List <Version >> versions , List <Version > unreleasedVersions ) {
102+ List <Version > lastMinor = new ArrayList <>(versions .get (versions .size () - 1 ));
103+ Version lastVersion = lastMinor .remove (lastMinor .size () - 1 );
104+ if (lastMinor .isEmpty ()) {
105+ versions .remove (versions .size () - 1 );
106+ } else {
107+ versions .set (versions .size () - 1 , lastMinor );
118108 }
119- return new Tuple <>(unmodifiableList (versions ), unmodifiableList (Arrays .asList (unreleased , current )));
109+ unreleasedVersions .add (lastVersion );
110+ return lastVersion ;
120111 }
121112
122113 private static final List <Version > RELEASED_VERSIONS ;
@@ -131,7 +122,7 @@ static Tuple<List<Version>, List<Version>> resolveReleasedVersions(Version curre
131122 allVersions .addAll (RELEASED_VERSIONS );
132123 allVersions .addAll (UNRELEASED_VERSIONS );
133124 Collections .sort (allVersions );
134- ALL_VERSIONS = unmodifiableList (allVersions );
125+ ALL_VERSIONS = Collections . unmodifiableList (allVersions );
135126 }
136127
137128 /**
@@ -244,5 +235,4 @@ public static Version maxCompatibleVersion(Version version) {
244235 assert compatible .size () > 0 ;
245236 return compatible .get (compatible .size () - 1 );
246237 }
247-
248238}
0 commit comments