Wsdl11AttachmentPolicyProviderTest.java

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.cxf.ws.policy.attachment.wsdl11;

import java.net.URL;
import java.util.List;

import javax.wsdl.WSDLException;
import javax.xml.namespace.QName;

import org.apache.cxf.Bus;
import org.apache.cxf.binding.BindingFactoryManager;
import org.apache.cxf.configuration.ConfiguredBeanLocator;
import org.apache.cxf.helpers.CastUtils;
import org.apache.cxf.service.model.BindingMessageInfo;
import org.apache.cxf.service.model.BindingOperationInfo;
import org.apache.cxf.service.model.EndpointInfo;
import org.apache.cxf.service.model.ServiceInfo;
import org.apache.cxf.transport.DestinationFactoryManager;
import org.apache.cxf.ws.policy.AssertionBuilderRegistry;
import org.apache.cxf.ws.policy.AssertionBuilderRegistryImpl;
import org.apache.cxf.ws.policy.PolicyBuilder;
import org.apache.cxf.ws.policy.PolicyBuilderImpl;
import org.apache.cxf.ws.policy.PolicyEngine;
import org.apache.cxf.ws.policy.PolicyException;
import org.apache.cxf.ws.policy.PolicyRegistryImpl;
import org.apache.cxf.ws.policy.builder.primitive.PrimitiveAssertionBuilder;
import org.apache.cxf.wsdl.WSDLManager;
import org.apache.cxf.wsdl11.WSDLManagerImpl;
import org.apache.cxf.wsdl11.WSDLServiceBuilder;
import org.apache.neethi.Constants;
import org.apache.neethi.Policy;
import org.apache.neethi.PolicyComponent;
import org.apache.neethi.util.PolicyComparator;

import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
 *
 */
public class Wsdl11AttachmentPolicyProviderTest {

    private static final String NAMESPACE_URI = "http://apache.org/cxf/calculator";
    private static final QName OPERATION_NAME = new QName(NAMESPACE_URI, "add");
    private static ServiceInfo[] services;
    private static EndpointInfo[] endpoints;
    private Wsdl11AttachmentPolicyProvider app;
    private Bus bus;


    @BeforeClass
    public static void oneTimeSetUp() throws Exception {
        Bus bus = mock(Bus.class);
        WSDLManager manager = new WSDLManagerImpl();
        WSDLServiceBuilder builder = new WSDLServiceBuilder(bus);
        DestinationFactoryManager dfm = mock(DestinationFactoryManager.class);
        when(bus.getExtension(DestinationFactoryManager.class)).thenReturn(dfm);
        when(dfm.getDestinationFactory(isA(String.class))).thenReturn(null);
        BindingFactoryManager bfm = mock(BindingFactoryManager.class);
        when(bus.getExtension(BindingFactoryManager.class)).thenReturn(bfm);
        when(bfm.getBindingFactory(isA(String.class))).thenReturn(null);

        int n = 19;
        services = new ServiceInfo[n];
        endpoints = new EndpointInfo[n];
        for (int i = 0; i < n; i++) {
            String resourceName = "/attachment/wsdl11/test" + i + ".wsdl";
            URL url = Wsdl11AttachmentPolicyProviderTest.class.getResource(resourceName);
            try {
                services[i] = builder.buildServices(manager.getDefinition(url.toString())).get(0);
            } catch (WSDLException ex) {
                ex.printStackTrace();
                fail("Failed to build service from resource " + resourceName);
            }
            assertNotNull(services[i]);
            endpoints[i] = services[i].getEndpoints().iterator().next();
            assertNotNull(endpoints[i]);
        }
    }

    @AfterClass
    public static void oneTimeTearDown() {
        endpoints = null;
        services = null;

    }

    @Before
    public void setUp() {
        bus = mock(Bus.class);
        when(bus.getExtension(ConfiguredBeanLocator.class)).thenReturn(null);
        AssertionBuilderRegistry abr = new AssertionBuilderRegistryImpl();
        abr.setIgnoreUnknownAssertions(false);


        PrimitiveAssertionBuilder ab = new PrimitiveAssertionBuilder();
        abr.registerBuilder(new QName("http://cxf.apache.org/test/assertions", "A"), ab);
        abr.registerBuilder(new QName("http://cxf.apache.org/test/assertions", "B"), ab);
        abr.registerBuilder(new QName("http://cxf.apache.org/test/assertions", "C"), ab);

        PolicyBuilderImpl pb = new PolicyBuilderImpl();
        when(bus.getExtension(PolicyBuilder.class)).thenReturn(pb);
        when(bus.getExtension(PolicyEngine.class)).thenReturn(null);

        pb.setAssertionBuilderRegistry(abr);
        app = new Wsdl11AttachmentPolicyProvider();
        app.setBuilder(pb);
        app.setRegistry(new PolicyRegistryImpl());
    }

    @Test
    public void testElementPolicies() throws WSDLException {

        Policy p;

        // no extensions
        p = app.getElementPolicy(services[0]);
        assertTrue(p == null || p.isEmpty());

        // extensions not of type Policy or PolicyReference
        p = app.getElementPolicy(services[1]);
        assertTrue(p == null || p.isEmpty());

        // one extension of type Policy, without assertion builder
        try {
            app.getElementPolicy(services[2]);
            fail("Expected PolicyException not thrown.");
        } catch (PolicyException ex) {
            // expected
        }

        // one extension of type Policy
        p = app.getElementPolicy(services[3]);
        assertNotNull(p);
        assertFalse(p.isEmpty());
        verifyAssertionsOnly(p, 2);

        // two extensions of type Policy
        p = app.getElementPolicy(services[4]);
        assertNotNull(p);
        assertFalse(p.isEmpty());
        verifyAssertionsOnly(p, 3);

        EndpointInfo ei = new EndpointInfo();
        assertNull(app.getElementPolicy(ei));
    }

    @Test
    public void testEffectiveServicePolicies() throws WSDLException {

        Policy p;
        Policy ep;

        // no extensions
        ep = app.getEffectivePolicy(services[0], null);
        assertTrue(ep == null || ep.isEmpty());
        p = app.getElementPolicy(services[0]);
        assertTrue(p == null || p.isEmpty());

        // extensions not of type Policy or PolicyReference
        ep = app.getEffectivePolicy(services[1], null);
        assertTrue(ep == null || ep.isEmpty());

        // one extension of type Policy, without assertion builder
        try {
            app.getEffectivePolicy(services[2], null);
            fail("Expected PolicyException not thrown.");
        } catch (PolicyException ex) {
            // expected
        }

        // one extension of type Policy
        ep = app.getEffectivePolicy(services[3], null);
        assertNotNull(ep);
        assertFalse(ep.isEmpty());
        verifyAssertionsOnly(ep, 2);
        p = app.getElementPolicy(services[3]);
        assertTrue(PolicyComparator.compare(p, ep));

        // two extensions of type Policy
        ep = app.getEffectivePolicy(services[4], null);
        assertNotNull(ep);
        assertFalse(ep.isEmpty());
        verifyAssertionsOnly(ep, 3);
        p = app.getElementPolicy(services[4]);
        assertTrue(PolicyComparator.compare(p, ep));
    }

    @Test
    public void testEffectiveEndpointPolicies() {
        Policy ep;
        Policy p;

        // port has no extensions
        // porttype has no extensions
        // binding has no extensions
        ep = app.getEffectivePolicy(endpoints[0], null);
        assertTrue(ep == null || ep.isEmpty());

        // port has one extension of type Policy
        // binding has no extensions
        // porttype has no extensions
        ep = app.getEffectivePolicy(endpoints[5], null);
        assertNotNull(ep);
        assertFalse(ep.isEmpty());
        verifyAssertionsOnly(ep, 1);
        p = app.getElementPolicy(endpoints[5]);
        assertTrue(PolicyComparator.compare(p, ep));

        // port has no extensions
        // binding has one extension of type Policy
        // porttype has no extensions
        ep = app.getEffectivePolicy(endpoints[6], null);
        assertNotNull(ep);
        assertFalse(ep.isEmpty());
        verifyAssertionsOnly(ep, 1);
        p = app.getElementPolicy(endpoints[6].getBinding());
        assertTrue(PolicyComparator.compare(p, ep));

        // port has no extensions
        // binding has no extensions
        // porttype has one extension of type Policy
        ep = app.getEffectivePolicy(endpoints[7], null);
        assertNotNull(ep);
        assertFalse(ep.isEmpty());
        verifyAssertionsOnly(ep, 1);
        p = app.getElementPolicy(endpoints[7].getInterface());
        assertTrue(PolicyComparator.compare(p, ep));

        // port has one extension of type Policy
        // porttype has one extension of type Policy
        // binding has one extension of type Policy
        ep = app.getEffectivePolicy(endpoints[8], null);
        assertNotNull(ep);
        assertFalse(ep.isEmpty());
        verifyAssertionsOnly(ep, 3);

        // port has no extensions
        // binding has no extensions
        // porttype has no extension elements but one extension attribute of type PolicyURIs
        // consisting of two references (one local, one external)

        ep = app.getEffectivePolicy(endpoints[18], null);
        assertNotNull(ep);
        assertFalse(ep.isEmpty());
        verifyAssertionsOnly(ep, 2);
    }

    @Test
    public void testEffectiveBindingOperationPolicies() {
        Policy ep;

        // operation has no extensions
        // binding operation has no extensions
        ep = app.getEffectivePolicy(getBindingOperationInfo(endpoints[0]), null);
        assertTrue(ep == null || ep.isEmpty());

        // operation has no extensions
        // binding operation has one extension of type Policy
        ep = app.getEffectivePolicy(getBindingOperationInfo(endpoints[9]), null);
        assertNotNull(ep);
        assertFalse(ep.isEmpty());
        verifyAssertionsOnly(ep, 1);

        // operation has one extension of type Policy
        // binding operation has no extensions
        ep = app.getEffectivePolicy(getBindingOperationInfo(endpoints[10]), null);
        assertNotNull(ep);
        assertFalse(ep.isEmpty());
        verifyAssertionsOnly(ep, 2);

        // operation has one extension of type Policy
        // binding operation one extension of type Policy
        ep = app.getEffectivePolicy(getBindingOperationInfo(endpoints[11]), null);
        assertNotNull(ep);
        assertFalse(ep.isEmpty());
        verifyAssertionsOnly(ep, 3);
    }

    @Test
    public void testEffectiveMessagePolicies() {
        Policy ep;

        // binding operation message has no extensions
        // operation message has no extensions
        // message has no extensions
        ep = app.getEffectivePolicy(getBindingMessageInfo(endpoints[0], true), null);
        assertTrue(ep == null || ep.isEmpty());

        // binding operation message has one extension of type Policy
        // operation message has no extensions
        // message has no extensions
        ep = app.getEffectivePolicy(getBindingMessageInfo(endpoints[12], true), null);
        assertFalse(ep.isEmpty());
        verifyAssertionsOnly(ep, 1);

        // binding operation message has no extensions
        // operation message has one extension of type Policy
        // message has no extensions
        ep = app.getEffectivePolicy(getBindingMessageInfo(endpoints[13], true), null);
        assertFalse(ep.isEmpty());
        verifyAssertionsOnly(ep, 1);

        // binding operation message has no extensions
        // operation message has no extensions
        // message has one extension of type Policy
        ep = app.getEffectivePolicy(getBindingMessageInfo(endpoints[14], true), null);
        assertFalse(ep.isEmpty());
        verifyAssertionsOnly(ep, 1);

        // binding operation message has one extension of type Policy
        // operation message has one extension of type Policy
        // message has one extension of type Policy
        ep = app.getEffectivePolicy(getBindingMessageInfo(endpoints[15], true), null);
        assertFalse(ep.isEmpty());
        verifyAssertionsOnly(ep, 3);
    }

    @Test
    public void testResolveLocal() {

        Policy ep;

        // service has one extension of type PolicyReference, reference can be resolved locally
        ep = app.getElementPolicy(services[16]);
        assertNotNull(ep);
        verifyAssertionsOnly(ep, 2);

        // port has one extension of type PolicyReference, reference cannot be resolved locally
        try {
            app.getElementPolicy(endpoints[16]);
            fail("Expected PolicyException not thrown.");
        } catch (PolicyException ex) {
            // expected
        }
    }

    @Test
    public void testResolveExternal() {
        // service has one extension of type PolicyReference, reference is external
        Policy p = app.getElementPolicy(services[17]);
        verifyAssertionsOnly(p, 2);

        // port has one extension of type PolicyReference, reference cannot be resolved because
        // referenced document does not contain policy with the required if
        try {
            app.getElementPolicy(endpoints[17]);
            fail("Expected PolicyException not thrown.");
        } catch (PolicyException ex) {
            // expected
        }

        // binding has one extension of type PolicyReference, reference cannot be resolved because
        // referenced document cannot be found
        try {
            app.getElementPolicy(endpoints[17].getBinding());
            fail("Expected PolicyException not thrown.");
        } catch (PolicyException ex) {
            // expected
        }
    }


    private void verifyAssertionsOnly(Policy p, int expectedAssertions) {
        List<PolicyComponent> pcs;
        pcs = CastUtils.cast(p.getAssertions(), PolicyComponent.class);
        assertEquals(expectedAssertions, pcs.size());
        for (int i = 0; i < expectedAssertions; i++) {
            assertEquals(Constants.TYPE_ASSERTION, pcs.get(i).getType());
        }
    }

    private BindingOperationInfo getBindingOperationInfo(EndpointInfo ei) {
        return ei.getBinding().getOperation(OPERATION_NAME);
    }

    private BindingMessageInfo getBindingMessageInfo(EndpointInfo ei, boolean in) {
        return in ? ei.getBinding().getOperation(OPERATION_NAME).getInput()
            : ei.getBinding().getOperation(OPERATION_NAME).getOutput();
    }


}