Skip to content

Commit 6ef76f8

Browse files
authored
Merge branch 'main' into fix-test-for-release
2 parents da5fd7f + d2387cf commit 6ef76f8

File tree

6 files changed

+393
-140
lines changed

6 files changed

+393
-140
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.gradle.internal.transport
11+
12+
import org.elasticsearch.gradle.fixtures.AbstractGradleFuncTest
13+
import org.gradle.testkit.runner.BuildResult
14+
import org.gradle.testkit.runner.TaskOutcome
15+
16+
class AbstractTransportVersionFuncTest extends AbstractGradleFuncTest {
17+
def javaResource(String project, String path, String content) {
18+
file("${project}/src/main/resources/${path}").withWriter { writer ->
19+
writer << content
20+
}
21+
}
22+
23+
def javaSource(String project, String packageName, String className, String imports, String content) {
24+
String packageSlashes = packageName.replace('.', '/')
25+
file("${project}/src/main/java/${packageSlashes}/${className}.java").withWriter { writer ->
26+
writer << """
27+
package ${packageName};
28+
${imports}
29+
public class ${className} {
30+
${content}
31+
}
32+
"""
33+
}
34+
}
35+
36+
def namedTransportVersion(String name, String ids) {
37+
javaResource("myserver", "transport/definitions/named/" + name + ".csv", ids)
38+
}
39+
40+
def unreferencedTransportVersion(String name, String id) {
41+
javaResource("myserver", "transport/definitions/unreferenced/" + name + ".csv", id)
42+
}
43+
44+
def definedAndUsedTransportVersion(String name, String ids) {
45+
return definedAndUsedTransportVersion(name, ids, "Test${name.capitalize()}")
46+
}
47+
48+
def definedAndUsedTransportVersion(String name, String ids, String classname) {
49+
javaSource("myserver", "org.elasticsearch", classname, "", """
50+
static final TransportVersion usage = TransportVersion.fromName("${name}");
51+
""")
52+
namedTransportVersion(name, ids)
53+
}
54+
55+
def latestTransportVersion(String branch, String name, String id) {
56+
javaResource("myserver", "transport/latest/" + branch + ".csv","${name},${id}")
57+
}
58+
59+
def validateReferencesFails(String project) {
60+
return gradleRunner(":${project}:validateTransportVersionReferences").buildAndFail()
61+
}
62+
63+
def validateDefinitionsFails() {
64+
return gradleRunner(":myserver:validateTransportVersionDefinitions").buildAndFail()
65+
}
66+
67+
def assertReferencesFailure(BuildResult result, String project, String expectedOutput) {
68+
result.task(":${project}:validateTransportVersionReferences").outcome == TaskOutcome.FAILED
69+
assertOutputContains(result.output, expectedOutput)
70+
}
71+
72+
def assertDefinitionsFailure(BuildResult result, String expectedOutput) {
73+
result.task(":myserver:validateTransportVersionDefinitions").outcome == TaskOutcome.FAILED
74+
assertOutputContains(result.output, expectedOutput)
75+
}
76+
77+
def setup() {
78+
configurationCacheCompatible = false
79+
internalBuild()
80+
settingsFile << """
81+
include ':myserver'
82+
include ':myplugin'
83+
"""
84+
file("gradle.properties") << """
85+
org.elasticsearch.transport.definitionsProject=:myserver
86+
"""
87+
88+
file("myserver/build.gradle") << """
89+
apply plugin: 'java-library'
90+
apply plugin: 'elasticsearch.transport-version-references'
91+
apply plugin: 'elasticsearch.transport-version-resources'
92+
"""
93+
namedTransportVersion("existing_91", "8012000")
94+
namedTransportVersion("existing_92", "8123000,8012001")
95+
unreferencedTransportVersion("initial_9_0_0", "8000000")
96+
latestTransportVersion("9.2", "existing_92", "8123000")
97+
latestTransportVersion("9.1", "existing_92", "8012001")
98+
// a mock version of TransportVersion, just here so we can compile Dummy.java et al
99+
javaSource("myserver", "org.elasticsearch", "TransportVersion", "", """
100+
public static TransportVersion fromName(String name) {
101+
return null;
102+
}
103+
""")
104+
javaSource("myserver", "org.elasticsearch", "Dummy", "", """
105+
static final TransportVersion existing91 = TransportVersion.fromName("existing_91");
106+
static final TransportVersion existing92 = TransportVersion.fromName("existing_92");
107+
""")
108+
109+
file("myplugin/build.gradle") << """
110+
apply plugin: 'java-library'
111+
apply plugin: 'elasticsearch.transport-version-references'
112+
113+
dependencies {
114+
implementation project(":myserver")
115+
}
116+
"""
117+
118+
setupLocalGitRepo()
119+
execute("git checkout -b main")
120+
execute("git checkout -b test")
121+
}
122+
}
Lines changed: 1 addition & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -10,124 +10,9 @@
1010
package org.elasticsearch.gradle.internal.transport
1111

1212

13-
import org.elasticsearch.gradle.fixtures.AbstractGradleFuncTest
14-
import org.gradle.testkit.runner.BuildResult
1513
import org.gradle.testkit.runner.TaskOutcome
1614

17-
class TransportVersionManagementPluginFuncTest extends AbstractGradleFuncTest {
18-
19-
/**
20-
*
21-
* @param project
22-
* @param path
23-
* @param content
24-
* @return
25-
*/
26-
def javaResource(String project, String path, String content) {
27-
file("${project}/src/main/resources/${path}").withWriter { writer ->
28-
writer << content
29-
}
30-
}
31-
32-
def javaSource(String project, String packageName, String className, String imports, String content) {
33-
String packageSlashes = packageName.replace('.', '/')
34-
file("${project}/src/main/java/${packageSlashes}/${className}.java").withWriter { writer ->
35-
writer << """
36-
package ${packageName};
37-
${imports}
38-
public class ${className} {
39-
${content}
40-
}
41-
"""
42-
}
43-
}
44-
45-
def namedTransportVersion(String name, String ids) {
46-
javaResource("myserver", "transport/definitions/named/" + name + ".csv", ids)
47-
}
48-
49-
def unreferencedTransportVersion(String name, String id) {
50-
javaResource("myserver", "transport/definitions/unreferenced/" + name + ".csv", id)
51-
}
52-
53-
def definedAndUsedTransportVersion(String name, String ids) {
54-
return definedAndUsedTransportVersion(name, ids, "Test${name.capitalize()}")
55-
}
56-
57-
def definedAndUsedTransportVersion(String name, String ids, String classname) {
58-
javaSource("myserver", "org.elasticsearch", classname, "", """
59-
static final TransportVersion usage = TransportVersion.fromName("${name}");
60-
""")
61-
namedTransportVersion(name, ids)
62-
}
63-
64-
def latestTransportVersion(String branch, String name, String id) {
65-
javaResource("myserver", "transport/latest/" + branch + ".csv","${name},${id}")
66-
}
67-
68-
def validateReferencesFails(String project) {
69-
return gradleRunner(":${project}:validateTransportVersionReferences").buildAndFail()
70-
}
71-
72-
def validateDefinitionsFails() {
73-
return gradleRunner(":myserver:validateTransportVersionDefinitions").buildAndFail()
74-
}
75-
76-
def assertReferencesFailure(BuildResult result, String project, String expectedOutput) {
77-
result.task(":${project}:validateTransportVersionReferences").outcome == TaskOutcome.FAILED
78-
assertOutputContains(result.output, expectedOutput)
79-
}
80-
81-
def assertDefinitionsFailure(BuildResult result, String expectedOutput) {
82-
result.task(":myserver:validateTransportVersionDefinitions").outcome == TaskOutcome.FAILED
83-
assertOutputContains(result.output, expectedOutput)
84-
}
85-
86-
def setup() {
87-
configurationCacheCompatible = false
88-
internalBuild()
89-
settingsFile << """
90-
include ':myserver'
91-
include ':myplugin'
92-
"""
93-
file("gradle.properties") << """
94-
org.elasticsearch.transport.definitionsProject=:myserver
95-
"""
96-
97-
file("myserver/build.gradle") << """
98-
apply plugin: 'java-library'
99-
apply plugin: 'elasticsearch.transport-version-references'
100-
apply plugin: 'elasticsearch.transport-version-resources'
101-
"""
102-
namedTransportVersion("existing_91", "8012000")
103-
namedTransportVersion("existing_92", "8123000,8012001")
104-
unreferencedTransportVersion("initial_9_0_0", "8000000")
105-
latestTransportVersion("9.2", "existing_92", "8123000")
106-
latestTransportVersion("9.1", "existing_92", "8012001")
107-
// a mock version of TransportVersion, just here so we can compile Dummy.java et al
108-
javaSource("myserver", "org.elasticsearch", "TransportVersion", "", """
109-
public static TransportVersion fromName(String name) {
110-
return null;
111-
}
112-
""")
113-
javaSource("myserver", "org.elasticsearch", "Dummy", "", """
114-
static final TransportVersion existing91 = TransportVersion.fromName("existing_91");
115-
static final TransportVersion existing92 = TransportVersion.fromName("existing_92");
116-
""")
117-
118-
file("myplugin/build.gradle") << """
119-
apply plugin: 'java-library'
120-
apply plugin: 'elasticsearch.transport-version-references'
121-
122-
dependencies {
123-
implementation project(":myserver")
124-
}
125-
"""
126-
127-
setupLocalGitRepo()
128-
execute("git checkout -b main")
129-
execute("git checkout -b test")
130-
}
15+
class TransportVersionValidationFuncTest extends AbstractTransportVersionFuncTest {
13116

13217
def "test setup works"() {
13318
when:

libs/core/src/main/java/org/elasticsearch/core/Glob.java

Lines changed: 69 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,34 +29,84 @@ public static boolean globMatch(String pattern, String str) {
2929
if (pattern == null || str == null) {
3030
return false;
3131
}
32-
int firstIndex = pattern.indexOf('*');
33-
if (firstIndex == -1) {
32+
33+
int patternIndex = pattern.indexOf('*');
34+
if (patternIndex == -1) {
35+
// Nothing to glob
3436
return pattern.equals(str);
3537
}
36-
if (firstIndex == 0) {
38+
39+
if (patternIndex == 0) {
40+
// If the pattern is a literal '*' then it matches any input
3741
if (pattern.length() == 1) {
3842
return true;
3943
}
40-
int nextIndex = pattern.indexOf('*', firstIndex + 1);
41-
if (nextIndex == -1) {
42-
return str.endsWith(pattern.substring(1));
43-
} else if (nextIndex == 1) {
44-
// Double wildcard "**" - skipping the first "*"
45-
return globMatch(pattern.substring(1), str);
44+
} else {
45+
if (str.regionMatches(0, pattern, 0, patternIndex) == false) {
46+
// If the pattern starts with a literal (i.e. not '*') then the input string must also start with that
47+
return false;
4648
}
47-
String part = pattern.substring(1, nextIndex);
48-
int partIndex = str.indexOf(part);
49-
while (partIndex != -1) {
50-
if (globMatch(pattern.substring(nextIndex), str.substring(partIndex + part.length()))) {
51-
return true;
49+
if (patternIndex == pattern.length() - 1) {
50+
// The pattern is "something*", so if the starting region matches, then the whole pattern matches
51+
return true;
52+
}
53+
}
54+
55+
int strIndex = patternIndex;
56+
while (strIndex < str.length()) {
57+
assert pattern.charAt(patternIndex) == '*' : "Expected * at index " + patternIndex + " of [" + pattern + "]";
58+
59+
// skip over the '*'
60+
patternIndex++;
61+
62+
if (patternIndex == pattern.length()) {
63+
// The pattern ends in '*' (that is, "something*" or "*some*thing*", etc)
64+
// Since we already matched everything up to the '*' we know the string matches (whatever is left over must match '*')
65+
// so we're automatically done
66+
return true;
67+
}
68+
69+
// Look for the next '*'
70+
int nextStar = pattern.indexOf('*', patternIndex);
71+
while (nextStar == patternIndex) {
72+
// Two (or more) stars in sequence, just skip the subsequent ones
73+
patternIndex++;
74+
nextStar = pattern.indexOf('*', patternIndex);
75+
}
76+
if (nextStar == -1) {
77+
// We've come to the last '*' in a pattern (.e.g the 2nd one in "*some*thing")
78+
// In this case we match if the input string ends in "thing" (but constrained by the current position)
79+
final int len = pattern.length() - patternIndex;
80+
final int strSuffixStart = str.length() - len;
81+
if (strSuffixStart < strIndex) {
82+
// The suffix would start before the current position. That means it's not a match
83+
// e.g. "abc" is not a match for "ab*bc" even though "abc" does end with "bc"
84+
return false;
85+
}
86+
return str.regionMatches(strSuffixStart, pattern, patternIndex, len);
87+
} else {
88+
// There is another star, with a literal in between the current position and that '*'
89+
// That is, we have "*literal*"
90+
// We want the first '*' to consume everything up until the first occurrence of "literal" in the input string
91+
int match = str.indexOf(pattern.substring(patternIndex, nextStar), strIndex);
92+
if (match == -1) {
93+
// If "literal" isn't there, then the match fails.
94+
return false;
5295
}
53-
partIndex = str.indexOf(part, partIndex + 1);
96+
// Move both index (pointer) values to the end of the literal
97+
strIndex = match + (nextStar - patternIndex);
98+
patternIndex = nextStar;
5499
}
55-
return false;
56100
}
57-
return (str.length() >= firstIndex
58-
&& pattern.substring(0, firstIndex).equals(str.substring(0, firstIndex))
59-
&& globMatch(pattern.substring(firstIndex), str.substring(firstIndex)));
101+
102+
// We might have trailing '*'s in the pattern after completing a literal match at the end of the input string
103+
// e.g. a glob of "el*ic*" matching "elastic" - we need to consume that last '*' without it matching anything
104+
while (patternIndex < pattern.length() && pattern.charAt(patternIndex) == '*') {
105+
patternIndex++;
106+
}
107+
108+
// The match is successful only if we have consumed the entire pattern.
109+
return patternIndex == pattern.length();
60110
}
61111

62112
}

0 commit comments

Comments
 (0)