From d89586ea96d95602f6e5ce879c289e284b131cb6 Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Mon, 26 Jun 2017 10:37:49 +0100 Subject: [PATCH] [JENKINS-45130] Add tests to demonstrate issue --- .../describable/AbstractSharedName.java | 30 +++++++ .../describable/AmbiguousArrayContainer.java | 52 +++++++++++ .../describable/AmbiguousListContainer.java | 50 +++++++++++ .../describable/DescribableModelTest.java | 88 +++++++++++++++++++ .../structs/describable/first/SharedName.java | 73 +++++++++++++++ .../describable/second/SharedName.java | 48 ++++++++++ 6 files changed, 341 insertions(+) create mode 100644 plugin/src/test/java/org/jenkinsci/plugins/structs/describable/AbstractSharedName.java create mode 100644 plugin/src/test/java/org/jenkinsci/plugins/structs/describable/AmbiguousArrayContainer.java create mode 100644 plugin/src/test/java/org/jenkinsci/plugins/structs/describable/AmbiguousListContainer.java create mode 100644 plugin/src/test/java/org/jenkinsci/plugins/structs/describable/first/SharedName.java create mode 100644 plugin/src/test/java/org/jenkinsci/plugins/structs/describable/second/SharedName.java diff --git a/plugin/src/test/java/org/jenkinsci/plugins/structs/describable/AbstractSharedName.java b/plugin/src/test/java/org/jenkinsci/plugins/structs/describable/AbstractSharedName.java new file mode 100644 index 0000000..7d5d50d --- /dev/null +++ b/plugin/src/test/java/org/jenkinsci/plugins/structs/describable/AbstractSharedName.java @@ -0,0 +1,30 @@ +/* + * The MIT License + * + * Copyright (c) 2017, CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.jenkinsci.plugins.structs.describable; + +import hudson.model.AbstractDescribableImpl; + +public abstract class AbstractSharedName extends AbstractDescribableImpl { +} diff --git a/plugin/src/test/java/org/jenkinsci/plugins/structs/describable/AmbiguousArrayContainer.java b/plugin/src/test/java/org/jenkinsci/plugins/structs/describable/AmbiguousArrayContainer.java new file mode 100644 index 0000000..98c337f --- /dev/null +++ b/plugin/src/test/java/org/jenkinsci/plugins/structs/describable/AmbiguousArrayContainer.java @@ -0,0 +1,52 @@ +/* + * The MIT License + * + * Copyright (c) 2017, CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.jenkinsci.plugins.structs.describable; + +import hudson.Extension; +import hudson.model.AbstractDescribableImpl; +import hudson.model.Describable; +import hudson.model.Descriptor; +import org.kohsuke.stapler.DataBoundConstructor; + +public class AmbiguousArrayContainer extends AbstractDescribableImpl { + private final Describable[] array; + + @DataBoundConstructor + public AmbiguousArrayContainer(Describable... array) { + this.array = array.clone(); + } + + public Describable[] getArray() { + return array.clone(); + } + + @Extension + public static class DescriptorImpl extends Descriptor { + @Override + public String getDisplayName() { + return "ambiguous array container"; + } + } +} diff --git a/plugin/src/test/java/org/jenkinsci/plugins/structs/describable/AmbiguousListContainer.java b/plugin/src/test/java/org/jenkinsci/plugins/structs/describable/AmbiguousListContainer.java new file mode 100644 index 0000000..ab9c1f1 --- /dev/null +++ b/plugin/src/test/java/org/jenkinsci/plugins/structs/describable/AmbiguousListContainer.java @@ -0,0 +1,50 @@ +/* + * The MIT License + * + * Copyright (c) 2017, CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.jenkinsci.plugins.structs.describable; + +import hudson.Extension; +import hudson.model.AbstractDescribableImpl; +import hudson.model.Describable; +import hudson.model.Descriptor; +import java.util.ArrayList; +import java.util.List; +import org.kohsuke.stapler.DataBoundConstructor; + +public class AmbiguousListContainer extends AbstractDescribableImpl { + public final List> list; + + @DataBoundConstructor + public AmbiguousListContainer(List> list) { + this.list = new ArrayList>(list); + } + + @Extension + public static class DescriptorImpl extends Descriptor { + @Override + public String getDisplayName() { + return "ambiguous list container"; + } + } +} diff --git a/plugin/src/test/java/org/jenkinsci/plugins/structs/describable/DescribableModelTest.java b/plugin/src/test/java/org/jenkinsci/plugins/structs/describable/DescribableModelTest.java index 67086f5..af19290 100644 --- a/plugin/src/test/java/org/jenkinsci/plugins/structs/describable/DescribableModelTest.java +++ b/plugin/src/test/java/org/jenkinsci/plugins/structs/describable/DescribableModelTest.java @@ -27,6 +27,7 @@ import hudson.Extension; import hudson.model.AbstractDescribableImpl; import hudson.model.BooleanParameterValue; +import hudson.model.Describable; import hudson.model.Descriptor; import hudson.model.ParameterValue; import hudson.model.ParametersDefinitionProperty; @@ -41,6 +42,7 @@ import org.jenkinsci.plugins.structs.FishingNet; import org.jenkinsci.plugins.structs.Internet; import org.jenkinsci.plugins.structs.Tech; +import org.jenkinsci.plugins.structs.describable.first.SharedName; import org.junit.ClassRule; import org.junit.Test; import org.jvnet.hudson.test.Issue; @@ -59,6 +61,7 @@ import java.util.logging.Level; import static org.apache.commons.lang3.SerializationUtils.roundtrip; +import static org.hamcrest.Matchers.instanceOf; import static org.jenkinsci.plugins.structs.describable.DescribableModel.*; import static org.jenkinsci.plugins.structs.describable.UninstantiatedDescribable.ANONYMOUS_KEY; import static org.junit.Assert.*; @@ -764,6 +767,91 @@ public void ambiguousSimpleName() throws Exception { assertEquals(UnambiguousClassName.class.getSimpleName(), m2.get("$class")); } + @Issue("JENKINS-45130") // + @Test + public void ambiguousTopLevelSimpleName() throws Exception { + AmbiguousContainer container = new AmbiguousContainer(new SharedName("first"), + new UnambiguousClassName("second")); + + UninstantiatedDescribable ud = DescribableModel.uninstantiate2_(container); + + Object o = ud.toMap().get("ambiguous"); + assertTrue(o instanceof Map); + Map m = (Map)o; + + // Make sure the ambiguous class is fully qualified. + assertEquals(SharedName.class.getName(), m.get("$class")); + + Object o2 = ud.toMap().get("unambiguous"); + assertTrue(o2 instanceof Map); + Map m2 = (Map)o2; + + // Make sure the unambiguous class just uses the simple name. + assertEquals(UnambiguousClassName.class.getSimpleName(), m2.get("$class")); + } + + @Issue("JENKINS-45130") + @Test + public void ambiguousTopLevelSimpleNameInList() throws Exception { + SharedName first = new SharedName("first"); + first.setTwo("something"); + AmbiguousListContainer container = new AmbiguousListContainer(Arrays.>asList(first, + new UnambiguousClassName("second"))); + + UninstantiatedDescribable ud = DescribableModel.uninstantiate2_(container); + + Object o = ud.toMap().get("list"); + assertTrue(o instanceof List); + List> l = (List>) o; + + Map m = l.get(0); + + // Make sure the ambiguous class is fully qualified. + assertEquals(SharedName.class.getName(), m.get("$class")); + + Map m2 = l.get(1); + + // Make sure the unambiguous class just uses the simple name. + assertEquals(UnambiguousClassName.class.getSimpleName(), m2.get("$class")); + + System.out.println(ud.toString()); + + AmbiguousListContainer roundtrip = (AmbiguousListContainer) ud.instantiate(); + assertThat(roundtrip.list.get(0), instanceOf(SharedName.class)); + assertThat(roundtrip.list.get(1), instanceOf(UnambiguousClassName.class)); + } + + @Issue("JENKINS-45130") + @Test + public void ambiguousTopLevelSimpleNameInArray() throws Exception { + SharedName first = new SharedName("first"); + first.setTwo("something"); + AmbiguousArrayContainer container = new AmbiguousArrayContainer(first, + new UnambiguousClassName("second")); + + UninstantiatedDescribable ud = DescribableModel.uninstantiate2_(container); + + Object o = ud.toMap().get("array"); + assertTrue(o instanceof List); + List> l = (List>) o; + + Map m = l.get(0); + + // Make sure the ambiguous class is fully qualified. + assertEquals(SharedName.class.getName(), m.get("$class")); + + Map m2 = l.get(1); + + // Make sure the unambiguous class just uses the simple name. + assertEquals(UnambiguousClassName.class.getSimpleName(), m2.get("$class")); + + System.out.println(ud.toString()); + + AmbiguousArrayContainer roundtrip = (AmbiguousArrayContainer) ud.instantiate(); + assertThat(roundtrip.getArray()[0], instanceOf(SharedName.class)); + assertThat(roundtrip.getArray()[1], instanceOf(UnambiguousClassName.class)); + } + private static Map map(Object... keysAndValues) { if (keysAndValues.length % 2 != 0) { throw new IllegalArgumentException(); diff --git a/plugin/src/test/java/org/jenkinsci/plugins/structs/describable/first/SharedName.java b/plugin/src/test/java/org/jenkinsci/plugins/structs/describable/first/SharedName.java new file mode 100644 index 0000000..777ec35 --- /dev/null +++ b/plugin/src/test/java/org/jenkinsci/plugins/structs/describable/first/SharedName.java @@ -0,0 +1,73 @@ +/* + * The MIT License + * + * Copyright (c) 2017, CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.jenkinsci.plugins.structs.describable.first; + +import hudson.Extension; +import hudson.model.Descriptor; +import org.jenkinsci.Symbol; +import org.jenkinsci.plugins.structs.describable.AbstractSharedName; +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.DataBoundSetter; + +public class SharedName extends AbstractSharedName { + private final String one; + private String two; + + @DataBoundConstructor + public SharedName(String one) { + this.one = one; + } + + public String getOne() { + return one; + } + + public String getTwo() { + return two; + } + + @DataBoundSetter + public void setTwo(String two) { + this.two = two; + } + + public String getLegacyTwo() { + return two; + } + + @Deprecated + @DataBoundSetter + public void setLegacyTwo(String two) { + this.two = two; + } + + @Extension + public static class DescriptorImpl extends Descriptor { + @Override + public String getDisplayName() { + return "first.SharedName"; + } + } +} diff --git a/plugin/src/test/java/org/jenkinsci/plugins/structs/describable/second/SharedName.java b/plugin/src/test/java/org/jenkinsci/plugins/structs/describable/second/SharedName.java new file mode 100644 index 0000000..bfd9e39 --- /dev/null +++ b/plugin/src/test/java/org/jenkinsci/plugins/structs/describable/second/SharedName.java @@ -0,0 +1,48 @@ +/* + * The MIT License + * + * Copyright (c) 2017, CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.jenkinsci.plugins.structs.describable.second; + +import hudson.Extension; +import hudson.model.Descriptor; +import org.jenkinsci.Symbol; +import org.jenkinsci.plugins.structs.describable.AbstractSharedName; +import org.kohsuke.stapler.DataBoundConstructor; + +public class SharedName extends AbstractSharedName { + public final String two; + + @DataBoundConstructor + public SharedName(String two) { + this.two = two; + } + + @Extension + public static class DescriptorImpl extends Descriptor { + @Override + public String getDisplayName() { + return "second.SharedName"; + } + } +}