/* * The MIT License (MIT) * * Copyright (c) 2017-2019 Yegor Bugayenko * * 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 NON-INFRINGEMENT. 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.jpeek.skeleton; import com.jcabi.matchers.XhtmlMatchers; import org.jpeek.Base; import org.jpeek.FakeBase; import org.junit.jupiter.api.Test; import org.llorllale.cactoos.matchers.Assertion; /** * Test case for {@link Skeleton}. * @since 0.23 * @checkstyle JavadocMethodCheck (500 lines) */ @SuppressWarnings("PMD.AvoidDuplicateLiterals") public final class SkeletonTest { @Test public void createsXml() { new Assertion<>( "Must overload bar's methods", XhtmlMatchers.xhtml( new Skeleton( new FakeBase("OverloadMethods", "Bar") ).xml().toString() ), XhtmlMatchers.hasXPaths( // @checkstyle LineLength (10 lines) "/skeleton/app/package[count(class)=2]", "//class[@id='Bar']/methods[count(method)=5]", "//class[@id='OverloadMethods']/methods[count(method)=5]", "//method[@name='<init>' and @ctor='true']", "//class[@id='Bar']//method[@name='getKey']/ops[count(op)=3]", "//class[@id='Bar']//method[@name='getKey']/ops/op[@code='put_static' and .='Bar.singleton']", "//class[@id='Bar']//method[@name='getKey']/ops/op[@code='call']/name[text() ='java.lang.String.length']", "//class[@id='Bar']//method[@name='getKey']/ops/op[@code='get' and .='key']", "//class[@id='Bar']//method[@name='<init>']/ops[count(op)=4]" ) ).affirm(); } @Test public void skeletonShouldReflectExactOverloadedCalledMethod() { new Assertion<>( "Must find arguments of overloaded method", XhtmlMatchers.xhtml( new Skeleton( new FakeBase("OverloadMethods") ).xml().toString() ), XhtmlMatchers.hasXPaths( // @checkstyle LineLength (3 lines) "//method[@name='methodOne' and @desc='(Ljava/lang/String;)D']/ops/op[@code='call']/name[.='OverloadMethods.methodOne']", "//method[@name='methodOne' and @desc='(Ljava/lang/String;)D']/ops/op[@code='call']/args[count(arg)=2]", "//method[@name='methodOne' and @desc='(Ljava/lang/String;)D']/ops/op[@code='call']/args/arg[@type='Ljava/lang/String' and .='?']" ) ).affirm(); } @Test public void findsMethodsAndArgs() { new Assertion<>( "Must find methods with diff param types", XhtmlMatchers.xhtml( new Skeleton( new FakeBase("MethodsWithDiffParamTypes") ).xml().toString() ), XhtmlMatchers.hasXPaths( // @checkstyle LineLength (10 lines) "//class/methods[count(method)=7]", "//method[@name='methodSix']/args[count(arg)=1]", "//method[@name='methodSix']/args/arg[@type='Ljava/sql/Timestamp']", "//method[@name='methodSix' and return='Ljava/util/Date']", "//method[@name='methodTwo' and return='V']", "//method[@name='methodOne']/args/arg[@type='Ljava/lang/Object']" ) ).affirm(); } @Test public void findsMethodCalls() { new Assertion<>( "Must call methods", XhtmlMatchers.xhtml( new Skeleton( new FakeBase("Bar", "Foo") ).xml().toString() ), XhtmlMatchers.hasXPaths( // @checkstyle LineLength (10 lines) "//class[@id='Bar']/methods/method[@name='<init>' and @ctor='true']/ops/op/name[text() = 'java.lang.Object.<init>']", "//class[@id='Bar']/methods/method[@name='getKey']/ops/op/name[text() = 'java.lang.String.length']", "//class[@id='Bar']/methods/method[@name='getValue']/ops/op/name[text() = 'java.lang.String.length']", "//class[@id='Bar']/methods/method[@name='setValue']/ops/op/name[text() ='java.lang.UnsupportedOperationException.<init>']", "//class[@id='Foo']/methods/method[@name='methodOne']/ops/op/name[text() = 'Foo.methodTwo']", "//class[@id='Foo']/methods/method[@name='methodTwo']/ops/op/name[text() = 'Foo.methodOne']" ) ).affirm(); } @Test public void createsOnlyOneMethodIgnoresSynthetic() { new Assertion<>( "Must create only one method", XhtmlMatchers.xhtml( new Skeleton( new FakeBase("OneMethodCreatesLambda") ).xml().toString() ), XhtmlMatchers.hasXPaths( // @checkstyle LineLength (1 line) "//class[@id='OneMethodCreatesLambda' and count(methods/method[contains(@name,'doSomething')])=1]" ) ).affirm(); } @Test public void findFieldWithQualifiedName() { new Assertion<>( "Must find field with qualified name", XhtmlMatchers.xhtml( new Skeleton( new FakeBase( "ClassWithPublicField", "ClassAccessingPublicField" ) ) .xml() .toString() ), XhtmlMatchers.hasXPaths( // @checkstyle LineLength (1 line) "//class[@id='ClassAccessingPublicField']//method[@name='test']/ops/op[@code='put_static' and .='org.jpeek.samples.ClassWithPublicField.NAME']" ) ).affirm(); } @Test public void findSchemaOfSkeleton() { new Assertion<>( "Must find schema of skeleton", XhtmlMatchers.xhtml( new Skeleton( new FakeBase( "ClassWithDifferentMethodVisibilities" ) ) .xml() .toString() ), XhtmlMatchers.hasXPaths("//skeleton[@schema='xsd/skeleton.xsd']") ).affirm(); } @Test public void recognizesPublicMethods() { new Assertion<>( "Must recognize public methods", XhtmlMatchers.xhtml( new Skeleton( new FakeBase( "ClassWithDifferentMethodVisibilities" ) ) .xml() .toString() ), XhtmlMatchers.hasXPaths( "//method[@name='publicMethod' and @visibility='public']", "//method[@name='defaultMethod' and @visibility='default']", "//method[@name='protectedMethod' and @visibility='protected']", "//method[@name='privateMethod' and @visibility='private']" ) ).affirm(); } @Test public void acceptsSimilarClassNamesInDifferentPackages() { new Assertion<>( "Must not conflict when class names are identical", XhtmlMatchers.xhtml( new Skeleton( new Base.Concat( new FakeBase("foo/Foo", "bar/Foo"), new FakeBase("foo/Foo") ) ).xml().toString() ), XhtmlMatchers.hasXPaths( "/skeleton[count(//class) = 2]", "//class[@id='Foo']" ) ).affirm(); } }