Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<gitHubRepo>jenkinsci/${project.artifactId}-plugin</gitHubRepo>
<hpi.strictBundledArtifacts>true</hpi.strictBundledArtifacts>
<hpi.bundledArtifacts>groovy-sandbox</hpi.bundledArtifacts>
<ban-junit4-imports.skip>false</ban-junit4-imports.skip>
</properties>
<licenses>
<license>
Expand Down Expand Up @@ -87,5 +88,11 @@
<artifactId>test-harness</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>4.3.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,24 @@
import org.codehaus.groovy.runtime.GStringImpl;
import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.EnumeratingWhitelist;
import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.EnumeratingWhitelistTest;
import static org.junit.Assert.*;
import org.junit.Test;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

import org.jvnet.hudson.test.Issue;

public class GroovyCallSiteSelectorTest {
class GroovyCallSiteSelectorTest {

@Test public void arrays() throws Exception {
@Test
void arrays() throws Exception {
Method m = EnumeratingWhitelistTest.C.class.getDeclaredMethod("m", Object[].class);
assertEquals("literal call", m, GroovyCallSiteSelector.method(new EnumeratingWhitelistTest.C(), "m", new Object[] {new Object[] {"a", "b"}}));
assertNull("we assume the interceptor has dealt with varargs", GroovyCallSiteSelector.method(new EnumeratingWhitelistTest.C(), "m", new Object[]{"a", "b"}));
assertEquals("array cast", m, GroovyCallSiteSelector.method(new EnumeratingWhitelistTest.C(), "m", new Object[] {new String[] {"a", "b"}}));
assertEquals(m, GroovyCallSiteSelector.method(new EnumeratingWhitelistTest.C(), "m", new Object[] {new Object[] {"a", "b"}}), "literal call");
assertNull(GroovyCallSiteSelector.method(new EnumeratingWhitelistTest.C(), "m", new Object[]{"a", "b"}), "we assume the interceptor has dealt with varargs");
assertEquals(m, GroovyCallSiteSelector.method(new EnumeratingWhitelistTest.C(), "m", new Object[] {new String[] {"a", "b"}}), "array cast");
}

@Test public void overloads() throws Exception {
@Test
void overloads() throws Exception {
PrintWriter receiver = new PrintWriter(new OutputStream() {
@Override
public void write(int b) throws IOException {
Expand All @@ -69,33 +73,38 @@ public void write(int b) throws IOException {
}

@Issue("JENKINS-29541")
@Test public void methodsOnGString() throws Exception {
@Test
void methodsOnGString() throws Exception {
GStringImpl gString = new GStringImpl(new Object[0], new String[] {"x"});
assertEquals(String.class.getMethod("substring", int.class), GroovyCallSiteSelector.method(gString, "substring", new Object[] {99}));
assertEquals(GString.class.getMethod("getValues"), GroovyCallSiteSelector.method(gString, "getValues", new Object[0]));
assertEquals(GString.class.getMethod("getStrings"), GroovyCallSiteSelector.method(gString, "getStrings", new Object[0]));
}

@Issue("JENKINS-31701")
@Test public void primitives() throws Exception {
@Test
void primitives() throws Exception {
assertEquals(Primitives.class.getMethod("m1", long.class), GroovyCallSiteSelector.staticMethod(Primitives.class, "m1", new Object[] {Long.MAX_VALUE}));
assertEquals(Primitives.class.getMethod("m1", long.class), GroovyCallSiteSelector.staticMethod(Primitives.class, "m1", new Object[] {99}));
assertEquals(Primitives.class.getMethod("m2", long.class), GroovyCallSiteSelector.staticMethod(Primitives.class, "m2", new Object[] {Long.MAX_VALUE}));
assertEquals(Primitives.class.getMethod("m2", int.class), GroovyCallSiteSelector.staticMethod(Primitives.class, "m2", new Object[] {99}));
}

public static class Primitives {
public static void m1(long x) {}
public static void m2(int x) {}
public static void m2(long x) {}
}

@Test public void staticMethodsCannotBeOverridden() throws Exception {
@Test
void staticMethodsCannotBeOverridden() throws Exception {
assertEquals(Jenkins.class.getMethod("getInstance"), GroovyCallSiteSelector.staticMethod(Jenkins.class, "getInstance", new Object[0]));
assertEquals(Hudson.class.getMethod("getInstance"), GroovyCallSiteSelector.staticMethod(Hudson.class, "getInstance", new Object[0]));
}

@Issue("JENKINS-45117")
@Test public void constructorVarargs() throws Exception {
@Test
void constructorVarargs() throws Exception {
assertEquals(EnvVars.class.getConstructor(), GroovyCallSiteSelector.constructor(EnvVars.class, new Object[0]));
assertEquals(EnvVars.class.getConstructor(String[].class), GroovyCallSiteSelector.constructor(EnvVars.class, new Object[]{"x"}));
List<ParameterValue> params = new ArrayList<>();
Expand All @@ -115,7 +124,7 @@ public static void m2(long x) {}

@Issue("JENKINS-47159")
@Test
public void varargsFailureCases() throws Exception {
void varargsFailureCases() {
// If there's a partial match, we should get a ClassCastException
final ClassCastException e = assertThrows(ClassCastException.class,
() -> assertNull(GroovyCallSiteSelector.constructor(ParametersAction.class,
Expand All @@ -128,7 +137,7 @@ public void varargsFailureCases() throws Exception {

@Issue("JENKINS-37257")
@Test
public void varargsArrayElementTypeMismatch() throws Exception {
void varargsArrayElementTypeMismatch() throws Exception {
List<String> l = Arrays.asList("a", "b", "c");
assertEquals(String.class.getMethod("join", CharSequence.class, Iterable.class),
GroovyCallSiteSelector.staticMethod(String.class, "join", new Object[]{",", l}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,151 +2,142 @@

import org.jenkinsci.plugins.scriptsecurity.sandbox.Whitelist;
import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.GenericWhitelist;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ErrorCollector;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.jvnet.hudson.test.Issue;

public class GroovyLanguageCoverageTest {
class GroovyLanguageCoverageTest {

@Rule
public ErrorCollector errors = new ErrorCollector();

private void assertEvaluate(Whitelist whitelist, Object expected, String script) {
SandboxInterceptorTest.assertEvaluate(whitelist, expected, script, errors);
}

@Ignore("This fails on m.\"fruit${bKey}\" returning null due to JENKINS-46327")
@Disabled("This fails on m.\"fruit${bKey}\" returning null due to JENKINS-46327")
@Issue("JENKINS-46327")
@Test
public void quotedIdentifiers() throws Exception {
void quotedIdentifiers() throws Exception {
// See http://groovy-lang.org/syntax.html#_quoted_identifiers
assertEvaluate(new GenericWhitelist(),
true,
"def m = [fruitA: 'apple', fruitB: 'banana']\n" +
"assert m.fruitA == 'apple'\n" +
"assert m.'fruitA' == 'apple'\n" +
"assert m.\"fruitA\" == 'apple'\n" +
"assert m.'''fruitA''' == 'apple'\n" +
"assert m.\"\"\"fruitA\"\"\" == 'apple'\n" +
"assert m./fruitA/ == 'apple'\n" +
"assert m.$/fruitA/$ == 'apple'\n" +
"def bKey = 'B'\n" +
"assert m.\"fruit${bKey}\" == 'banana'\n" +
"assert m.\"\"\"fruit${bKey}\"\"\" == 'banana'" +
"assert m./fruit${bKey}/ == 'banana'\n" +
"assert m.$/fruit${bKey}/$ == 'banana'\n" +
"return true\n"
);
Whitelist whitelist = new GenericWhitelist();
SandboxInterceptorTest.assertEvaluate(whitelist, true, """
def m = [fruitA: 'apple', fruitB: 'banana']
assert m.fruitA == 'apple'
assert m.'fruitA' == 'apple'
assert m."fruitA" == 'apple'
assert m.'''fruitA''' == 'apple'
assert m.""\"fruitA""\" == 'apple'
assert m./fruitA/ == 'apple'
assert m.$/fruitA/$ == 'apple'
def bKey = 'B'
assert m."fruit${bKey}" == 'banana'
assert m.""\"fruit${bKey}""\" == 'banana'\
assert m./fruit${bKey}/ == 'banana'
assert m.$/fruit${bKey}/$ == 'banana'
return true
""");
}

@Test
public void gStringWithClosure() throws Exception {
void gStringWithClosure() throws Exception {
// see http://groovy-lang.org/syntax.html#_special_case_of_interpolating_closure_expressions
assertEvaluate(new GenericWhitelist(),
true,
"def number = 1\n" +
"def eagerGString = \"value == ${number}\"\n" +
"def lazyGString = \"value == ${ -> number }\"\n" +
"assert eagerGString == 'value == 1'\n" +
"assert lazyGString.toString() == 'value == 1'\n" +
"number = 2\n" +
"assert eagerGString == 'value == 1'\n" +
"assert lazyGString == 'value == 2'\n" +
"return true\n"
);
Whitelist whitelist = new GenericWhitelist();
SandboxInterceptorTest.assertEvaluate(whitelist, true, """
def number = 1
def eagerGString = "value == ${number}"
def lazyGString = "value == ${ -> number }"
assert eagerGString == 'value == 1'
assert lazyGString.toString() == 'value == 1'
number = 2
assert eagerGString == 'value == 1'
assert lazyGString == 'value == 2'
return true
""");
}

@Test
public void arithmeticOperators() throws Exception {
void arithmeticOperators() throws Exception {
// see http://groovy-lang.org/operators.html#_arithmetic_operators
assertEvaluate(new GenericWhitelist(),
true,
"assert 1 + 2 == 3\n" +
"assert 4 - 3 == 1\n" +
"assert 3 * 5 == 15\n" +
"assert 3 / 2 == 1.5\n" +
"assert 10 % 3 == 1\n" +
"assert 2 ** 3 == 8\n" +
"assert +3 == 3\n" +
"assert -4 == 0 - 4\n" +
"assert -(-1) == 1 \n" +
"def a = 2\n" +
"def b = a++ * 3\n" +
"assert a == 3 && b == 6\n" +
"def c = 3\n" +
"def d = c-- * 2\n" +
"assert c == 2 && d == 6\n" +
"def e = 1\n" +
"def f = ++e + 3\n" +
"assert e == 2 && f == 5\n" +
"def g = 4\n" +
"def h = --g + 1\n" +
"assert g == 3 && h == 4\n" +
"def a2 = 4\n" +
"a2 += 3\n" +
"assert a2 == 7\n" +
"def b2 = 5\n" +
"b2 -= 3\n" +
"assert b2 == 2\n" +
"def c2 = 5\n" +
"c2 *= 3\n" +
"assert c2 == 15\n" +
"def d2 = 10\n" +
"d2 /= 2\n" +
"assert d2 == 5\n" +
"def e2 = 10\n" +
"e2 %= 3\n" +
"assert e2 == 1\n" +
"def f2 = 3\n" +
"f2 **= 2\n" +
"assert f2 == 9\n" +
"return true\n"
);
Whitelist whitelist = new GenericWhitelist();
SandboxInterceptorTest.assertEvaluate(whitelist, true, """
assert 1 + 2 == 3
assert 4 - 3 == 1
assert 3 * 5 == 15
assert 3 / 2 == 1.5
assert 10 % 3 == 1
assert 2 ** 3 == 8
assert +3 == 3
assert -4 == 0 - 4
assert -(-1) == 1 \s
def a = 2
def b = a++ * 3
assert a == 3 && b == 6
def c = 3
def d = c-- * 2
assert c == 2 && d == 6
def e = 1
def f = ++e + 3
assert e == 2 && f == 5
def g = 4
def h = --g + 1
assert g == 3 && h == 4
def a2 = 4
a2 += 3
assert a2 == 7
def b2 = 5
b2 -= 3
assert b2 == 2
def c2 = 5
c2 *= 3
assert c2 == 15
def d2 = 10
d2 /= 2
assert d2 == 5
def e2 = 10
e2 %= 3
assert e2 == 1
def f2 = 3
f2 **= 2
assert f2 == 9
return true
""");
}

@Test
public void bigDecimalOperators() throws Exception {
void bigDecimalOperators() throws Exception {
// see http://groovy-lang.org/operators.html#_arithmetic_operators
assertEvaluate(new GenericWhitelist(),
true,
"assert 1.0 + 2.0 == 3.0\n" +
"assert 4.0 - 3.0 == 1.0\n" +
"assert 3.0 * 5.0 == 15.0\n" +
"assert 3.0 / 2.0 == 1.5\n" +
"assert 2.0 ** 3.0 == 8.0\n" +
"assert +3.0 == 3.0\n" +
"assert -4.0 == 0 - 4.0\n" +
"assert -(-1.0) == 1.0\n" +
"def a = 2.0\n" +
"def b = a++ * 3.0\n" +
"assert a == 3.0 && b == 6.0\n" +
"def c = 3.0\n" +
"def d = c-- * 2.0\n" +
"assert c == 2.0 && d == 6.0\n" +
"def e = 1.0\n" +
"def f = ++e + 3.0\n" +
"assert e == 2.0 && f == 5.0\n" +
"def g = 4.0\n" +
"def h = --g + 1.0\n" +
"assert g == 3.0 && h == 4.0\n" +
"def a2 = 4.0\n" +
"a2 += 3.0\n" +
"assert a2 == 7.0\n" +
"def b2 = 5.0\n" +
"b2 -= 3.0\n" +
"assert b2 == 2.0\n" +
"def c2 = 5.0\n" +
"c2 *= 3.0\n" +
"assert c2 == 15.0\n" +
"def d2 = 10.0\n" +
"d2 /= 2.0\n" +
"assert d2 == 5.0\n" +
"def f2 = 3.0\n" +
"f2 **= 2.0\n" +
"assert f2 == 9.0\n" +
"return true\n"
);
Whitelist whitelist = new GenericWhitelist();
SandboxInterceptorTest.assertEvaluate(whitelist, true, """
assert 1.0 + 2.0 == 3.0
assert 4.0 - 3.0 == 1.0
assert 3.0 * 5.0 == 15.0
assert 3.0 / 2.0 == 1.5
assert 2.0 ** 3.0 == 8.0
assert +3.0 == 3.0
assert -4.0 == 0 - 4.0
assert -(-1.0) == 1.0
def a = 2.0
def b = a++ * 3.0
assert a == 3.0 && b == 6.0
def c = 3.0
def d = c-- * 2.0
assert c == 2.0 && d == 6.0
def e = 1.0
def f = ++e + 3.0
assert e == 2.0 && f == 5.0
def g = 4.0
def h = --g + 1.0
assert g == 3.0 && h == 4.0
def a2 = 4.0
a2 += 3.0
assert a2 == 7.0
def b2 = 5.0
b2 -= 3.0
assert b2 == 2.0
def c2 = 5.0
c2 *= 3.0
assert c2 == 15.0
def d2 = 10.0
d2 /= 2.0
assert d2 == 5.0
def f2 = 3.0
f2 **= 2.0
assert f2 == 9.0
return true
""");
}
}
Loading
Loading