| /* |
| * 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.sling.models.impl; |
| |
| import static org.junit.Assert.*; |
| import static org.mockito.Mockito.*; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.concurrent.Callable; |
| import java.util.concurrent.ExecutionException; |
| import java.util.concurrent.ExecutorService; |
| import java.util.concurrent.Executors; |
| import java.util.concurrent.Future; |
| |
| import org.apache.sling.api.SlingHttpServletRequest; |
| import org.apache.sling.api.request.RequestPathInfo; |
| import org.apache.sling.api.resource.Resource; |
| import org.apache.sling.models.factory.ModelClassException; |
| import org.apache.sling.models.impl.injectors.RequestAttributeInjector; |
| import org.apache.sling.models.impl.injectors.SelfInjector; |
| import org.apache.sling.models.impl.via.BeanPropertyViaProvider; |
| import org.apache.sling.models.testmodels.classes.InvalidConstructorModel; |
| import org.apache.sling.models.testmodels.classes.SuperclassConstructorModel; |
| import org.apache.sling.models.testmodels.classes.WithOneConstructorModel; |
| import org.apache.sling.models.testmodels.classes.WithThreeConstructorsModel; |
| import org.apache.sling.models.testmodels.classes.WithTwoConstructorsModel; |
| import org.apache.sling.models.testmodels.classes.constructorinjection.NoNameModel; |
| import org.apache.sling.models.testmodels.classes.constructorinjection.ViaRequestSuffixModel; |
| import org.apache.sling.models.testmodels.classes.constructorinjection.WithThreeConstructorsOneInjectModel; |
| import org.hamcrest.Matchers; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.mockito.Mock; |
| import org.mockito.runners.MockitoJUnitRunner; |
| |
| @RunWith(MockitoJUnitRunner.class) |
| public class ConstructorTest { |
| |
| private ModelAdapterFactory factory; |
| |
| @Mock |
| private SlingHttpServletRequest request; |
| |
| private static final int INT_VALUE = 42; |
| |
| private static final String STRING_VALUE = "myValue"; |
| |
| @Before |
| public void setup() { |
| |
| when(request.getAttribute("attribute")).thenReturn(INT_VALUE); |
| when(request.getAttribute("attribute2")).thenReturn(STRING_VALUE); |
| |
| factory = AdapterFactoryTest.createModelAdapterFactory(); |
| factory.bindInjector(new RequestAttributeInjector(), new ServicePropertiesMap(1, 1)); |
| factory.bindInjector(new SelfInjector(), new ServicePropertiesMap(2, 2)); |
| factory.bindViaProvider(new BeanPropertyViaProvider(), null); |
| factory.adapterImplementations.addClassesAsAdapterAndImplementation( |
| WithOneConstructorModel.class, |
| WithThreeConstructorsModel.class, |
| WithTwoConstructorsModel.class, |
| SuperclassConstructorModel.class, |
| InvalidConstructorModel.class, |
| WithThreeConstructorsOneInjectModel.class, |
| NoNameModel.class, |
| ViaRequestSuffixModel.class |
| ); |
| } |
| |
| @Test |
| public void testConstructorInjection() { |
| WithOneConstructorModel model = factory.getAdapter(request, WithOneConstructorModel.class); |
| assertNotNull(model); |
| assertEquals(request, model.getRequest()); |
| assertEquals(INT_VALUE, model.getAttribute()); |
| } |
| |
| @Test |
| public void testThreeConstructorsInjection() { |
| WithThreeConstructorsModel model = factory.getAdapter(request, WithThreeConstructorsModel.class); |
| assertNotNull(model); |
| assertEquals(request, model.getRequest()); |
| assertEquals(INT_VALUE, model.getAttribute()); |
| } |
| |
| @Test |
| public void testTwoConstructorsInjection() { |
| WithTwoConstructorsModel model = factory.getAdapter(request, WithTwoConstructorsModel.class); |
| assertNotNull(model); |
| assertEquals(request, model.getRequest()); |
| assertEquals(INT_VALUE, model.getAttribute()); |
| } |
| |
| @Test |
| public void testSuperclassConstructorsInjection() { |
| SuperclassConstructorModel model = factory.getAdapter(request, SuperclassConstructorModel.class); |
| assertNotNull(model); |
| assertEquals(request, model.getRequest()); |
| assertEquals(INT_VALUE, model.getAttribute()); |
| } |
| |
| @Test |
| public void testInvalidConstructorInjector() { |
| InvalidConstructorModel model = factory.getAdapter(request, InvalidConstructorModel.class); |
| assertNull(model); |
| } |
| |
| @Test(expected = ModelClassException.class) |
| public void testInvalidConstructorInjectorException() { |
| factory.createModel(request, InvalidConstructorModel.class); |
| } |
| |
| /** |
| * Test model object with three constructors, and make sure that one with @Inject is picked for instantiation. |
| * Test mixing of constructor injection and field injection as well. |
| */ |
| @Test |
| public void testThreeConstructorsOneInjectInjection() { |
| WithThreeConstructorsOneInjectModel model = factory.getAdapter(request, |
| WithThreeConstructorsOneInjectModel.class); |
| assertNotNull(model); |
| assertNull(model.getRequest()); |
| assertEquals(INT_VALUE, model.getAttribute()); |
| assertEquals(STRING_VALUE, model.getAttribute2()); |
| } |
| |
| @Test |
| public void testMultiThreadedConstructorInjection() throws InterruptedException, ExecutionException { |
| |
| class ModelCreator implements Callable<String> { |
| @Override |
| public String call() throws Exception { |
| try { |
| WithOneConstructorModel model = factory.getAdapter(request, WithOneConstructorModel.class); |
| if (model == null) { |
| return "Expected model not null"; |
| } |
| if (!request.equals(model.getRequest())) { |
| return "Expected same request"; |
| } |
| if (INT_VALUE != model.getAttribute()) { |
| return "Expected same value for attribute"; |
| } |
| } catch (Throwable e) { |
| return "Exception not expected: " + e; |
| } |
| return null; |
| } |
| } |
| |
| int tries = 10000; |
| int threads = 10; |
| |
| ExecutorService executorService = Executors.newFixedThreadPool(threads); |
| List<ModelCreator> modelCreators = new ArrayList<>(tries); |
| for (int i = 0; i < tries; i++) { |
| modelCreators.add(new ModelCreator()); |
| } |
| List<Future<String>> futures = executorService.invokeAll(modelCreators); |
| executorService.shutdown(); |
| |
| for (Future<String> f : futures) { |
| String res = f.get(); |
| if (res != null) { |
| fail(res); |
| } |
| } |
| } |
| |
| @Test |
| public void testNoNameModel() { |
| NoNameModel model = factory.getAdapter(request, NoNameModel.class); |
| assertNull(model); |
| } |
| |
| @Test |
| public void testViaInjectionModel() throws Exception { |
| Resource suffixResource = mock(Resource.class); |
| when(suffixResource.getPath()).thenReturn("/the/suffix"); |
| |
| RequestPathInfo requestPathInfo = mock(RequestPathInfo.class); |
| when(requestPathInfo.getSuffixResource()).thenReturn(suffixResource); |
| |
| when(request.getRequestPathInfo()).thenReturn(requestPathInfo); |
| |
| ViaRequestSuffixModel model = factory.getAdapter(request, ViaRequestSuffixModel.class); |
| assertThat(model, Matchers.notNullValue()); |
| assertThat(model.getSuffix(), Matchers.is("/the/suffix")); |
| } |
| } |