com.ibm.jaggr.core.impl.module.ModuleImplTest.java Source code

Java tutorial

Introduction

Here is the source code for com.ibm.jaggr.core.impl.module.ModuleImplTest.java

Source

/*
 * (C) Copyright 2012, IBM Corporation
 *
 * Licensed 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 com.ibm.jaggr.core.impl.module;

import static org.junit.Assert.assertTrue;

import com.ibm.jaggr.core.IAggregator;
import com.ibm.jaggr.core.cachekeygenerator.ICacheKeyGenerator;
import com.ibm.jaggr.core.config.IConfig;
import com.ibm.jaggr.core.deps.IDependencies;
import com.ibm.jaggr.core.deps.ModuleDeps;
import com.ibm.jaggr.core.impl.config.ConfigImpl;
import com.ibm.jaggr.core.impl.module.ModuleImpl;
import com.ibm.jaggr.core.impl.modulebuilder.javascript.JavaScriptBuildRenderer;
import com.ibm.jaggr.core.impl.modulebuilder.javascript.JavaScriptModuleBuilder;
import com.ibm.jaggr.core.layer.ILayer;
import com.ibm.jaggr.core.test.TestUtils;
import com.ibm.jaggr.core.test.TestUtils.Ref;
import com.ibm.jaggr.core.transport.IHttpTransport;
import com.ibm.jaggr.core.util.CopyUtil;
import com.ibm.jaggr.core.util.Features;

import com.google.common.io.Files;

import org.apache.commons.lang.ArrayUtils;
import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import java.io.File;
import java.io.Reader;
import java.io.StringWriter;
import java.net.URI;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import junit.framework.Assert;

@RunWith(PowerMockRunner.class)
@PrepareForTest(JavaScriptModuleBuilder.class)
public class ModuleImplTest {

    static File tmpdir = null;
    IAggregator mockAggregator;
    Ref<IConfig> configRef = new Ref<IConfig>(null);
    Map<String, Object> requestAttributes = new HashMap<String, Object>();
    HttpServletRequest mockRequest;
    HttpServletResponse mockResponse = EasyMock.createNiceMock(HttpServletResponse.class);
    IDependencies mockDependencies = EasyMock.createMock(IDependencies.class);
    static final Map<String, String[]> testDepMap = TestUtils.createTestDepMap();

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        tmpdir = Files.createTempDir();
        TestUtils.createTestFiles(tmpdir);
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
        if (tmpdir != null) {
            TestUtils.deleteRecursively(tmpdir);
            tmpdir = null;
        }
    }

    @Before
    public void setup() throws Exception {
        mockAggregator = TestUtils.createMockAggregator(configRef, tmpdir);
        mockRequest = TestUtils.createMockRequest(mockAggregator, requestAttributes);
        EasyMock.expect(mockAggregator.getDependencies()).andReturn(mockDependencies).anyTimes();
        EasyMock.expect(mockDependencies.getLastModified()).andReturn(0L).anyTimes();
        EasyMock.expect(mockDependencies.getDelcaredDependencies(EasyMock.isA(String.class)))
                .andAnswer(new IAnswer<List<String>>() {
                    @Override
                    public List<String> answer() throws Throwable {
                        String name = (String) EasyMock.getCurrentArguments()[0];
                        String[] result = testDepMap.get(name);
                        return result != null ? Arrays.asList(result) : null;
                    }
                }).anyTimes();

        URI p1Path = new File(tmpdir, "p1").toURI();
        URI p2Path = new File(tmpdir, "p2").toURI();
        final Map<String, URI> map = new HashMap<String, URI>();
        map.put("p1", p1Path);
        map.put("p2", p2Path);

        EasyMock.replay(mockAggregator);
        EasyMock.replay(mockRequest);
        EasyMock.replay(mockResponse);
        EasyMock.replay(mockDependencies);
        requestAttributes.put(IAggregator.AGGREGATOR_REQATTRNAME, mockAggregator);
        requestAttributes.put(IHttpTransport.EXPANDREQUIRELISTS_REQATTRNAME, Boolean.TRUE);
    }

    @After
    public void tearDown() throws Exception {
        mockAggregator.getCacheManager().clearCache();
        for (File file : mockAggregator.getCacheManager().getCacheDir().listFiles()) {
            if (file.getName().startsWith("layer.")) {
                file.delete();
            }
        }
    }

    /*
     * Tests to make sure that the cache key generator for the module is properly updated
     * by requests that modify the dependent feature set (implemented via a path alias
     * config function).
     */
    @Test
    public void testModuleImpl() throws Exception {
        testDepMap.put("p2/a", (String[]) ArrayUtils.add(testDepMap.get("p2/a"), "p1/aliased/d"));
        String configJson = "{paths:{p1:'p1',p2:'p2'}, aliases:[[/\\/aliased\\//, function(s){if (has('foo')) return '/foo/'; else if (has('bar')) return '/bar/'; has('non'); return '/non/'}]]}";
        configRef.set(new ConfigImpl(mockAggregator, tmpdir.toURI(), configJson));

        Features features = new Features();
        features.put("foo", true);
        features.put("bar", true);
        requestAttributes.put(IHttpTransport.FEATUREMAP_REQATTRNAME, features);

        ModuleImpl module = (ModuleImpl) mockAggregator.newModule("p1/p1",
                mockAggregator.getConfig().locateModuleResource("p1/p1"));
        Reader reader = module.getBuild(mockRequest).get();
        System.out.println(module.toString());
        Assert.assertEquals("[expn, js:(has:[conditionFalse, conditionTrue, foo])]",
                module.getCacheKeyGenerators().toString());
        Assert.assertTrue(module.getKeys().size() == 1
                && module.getKeys().containsAll(Arrays.asList(new String[] { "expn:0;js:S:1:0:1;has{foo}" })));
        StringWriter writer = new StringWriter();
        CopyUtil.copy(reader, writer);
        String compiled = writer.toString();
        System.out.println(compiled);
        assertTrue(Pattern.compile("require\\(\\[.*?,\\\"p1/foo/d\\\".*?\\],").matcher(compiled).find());

        features.put("foo", false);
        reader = module.getBuild(mockRequest).get();
        System.out.println(module.toString());
        Assert.assertEquals("[expn, js:(has:[bar, conditionFalse, conditionTrue, foo])]",
                module.getCacheKeyGenerators().toString());
        Assert.assertTrue(module.getKeys().size() == 2 && module.getKeys().containsAll(
                Arrays.asList(new String[] { "expn:0;js:S:1:0:1;has{foo}", "expn:0;js:S:1:0:1;has{bar,!foo}" })));
        writer = new StringWriter();
        CopyUtil.copy(reader, writer);
        compiled = writer.toString();
        assertTrue(Pattern.compile("require\\(\\[.*?,\\\"p1/bar/d\\\".*?\\],").matcher(compiled).find());

        features.put("bar", false);
        reader = module.getBuild(mockRequest).get();
        System.out.println(module.toString());
        List<ICacheKeyGenerator> cacheKeyGenerators = module.getCacheKeyGenerators();
        Assert.assertEquals("[expn, js:(has:[bar, conditionFalse, conditionTrue, foo, non])]",
                module.getCacheKeyGenerators().toString());
        Assert.assertTrue(module.getKeys().size() == 3
                && module.getKeys().containsAll(Arrays.asList(new String[] { "expn:0;js:S:1:0:1;has{foo}",
                        "expn:0;js:S:1:0:1;has{bar,!foo}", "expn:0;js:S:1:0:1;has{!bar,!foo}" })));
        writer = new StringWriter();
        CopyUtil.copy(reader, writer);
        compiled = writer.toString();
        System.out.println(compiled);
        assertTrue(Pattern.compile("require\\(\\[.*?,\\\"p1/non/d\\\".*?\\],").matcher(compiled).find());

        features.remove("bar");
        features.put("foo", true);
        reader = module.getBuild(mockRequest).get();
        System.out.println(module.toString());
        Assert.assertTrue(cacheKeyGenerators == module.getCacheKeyGenerators());
        Assert.assertTrue(module.getKeys().size() == 3
                && module.getKeys().containsAll(Arrays.asList(new String[] { "expn:0;js:S:1:0:1;has{foo}",
                        "expn:0;js:S:1:0:1;has{bar,!foo}", "expn:0;js:S:1:0:1;has{!bar,!foo}" })));
        writer = new StringWriter();
        CopyUtil.copy(reader, writer);
        compiled = writer.toString();
        System.out.println(compiled);
        assertTrue(Pattern.compile("require\\(\\[.*?,\\\"p1/foo/d\\\".*?\\],").matcher(compiled).find());

        features.put("bar", true);
        reader = module.getBuild(mockRequest).get();
        System.out.println(module.toString());
        Assert.assertTrue(cacheKeyGenerators == module.getCacheKeyGenerators());
        Assert.assertTrue(module.getKeys().size() == 4 && module.getKeys().containsAll(
                Arrays.asList(new String[] { "expn:0;js:S:1:0:1;has{foo}", "expn:0;js:S:1:0:1;has{bar,foo}",
                        "expn:0;js:S:1:0:1;has{bar,!foo}", "expn:0;js:S:1:0:1;has{!bar,!foo}" })));
        writer = new StringWriter();
        CopyUtil.copy(reader, writer);
        compiled = writer.toString();
        assertTrue(Pattern.compile("require\\(\\[.*?,\\\"p1/foo/d\\\".*?\\],").matcher(compiled).find());
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testBuildRendererDependentFeatures() throws Exception {

        PowerMock
                .expectNew(JavaScriptBuildRenderer.class, EasyMock.isA(String.class), EasyMock.isA(String.class),
                        EasyMock.isA(List.class), EasyMock.eq(false))
                .andAnswer(new IAnswer<JavaScriptBuildRenderer>() {
                    @SuppressWarnings("serial")
                    @Override
                    public JavaScriptBuildRenderer answer() throws Throwable {
                        String mid = (String) EasyMock.getCurrentArguments()[0];
                        String content = (String) EasyMock.getCurrentArguments()[1];
                        List<ModuleDeps> depList = (List<ModuleDeps>) EasyMock.getCurrentArguments()[2];
                        Boolean isLogging = (Boolean) EasyMock.getCurrentArguments()[3];
                        return new JavaScriptBuildRenderer(mid, content, depList, isLogging) {
                            @Override
                            public String renderBuild(HttpServletRequest request, Set<String> dependentFeatures) {
                                dependentFeatures.add("feature1");
                                return super.renderBuild(request, dependentFeatures);
                            }
                        };
                    }

                }).anyTimes();
        PowerMock.replay(JavaScriptBuildRenderer.class);
        requestAttributes.put(IHttpTransport.EXPANDREQUIRELISTS_REQATTRNAME, Boolean.TRUE);
        configRef.set(new ConfigImpl(mockAggregator, tmpdir.toURI(), "{}"));
        requestAttributes.put(IHttpTransport.FEATUREMAP_REQATTRNAME, new Features());
        requestAttributes.put(ILayer.DEPENDENT_FEATURES, new HashSet<String>());
        ModuleImpl module = (ModuleImpl) mockAggregator.newModule("p1/p1",
                mockAggregator.getConfig().locateModuleResource("p1/p1"));
        Reader reader = module.getBuild(mockRequest).get();
        System.out.println(module.toString());
        StringWriter writer = new StringWriter();
        // make sure dependent features from build renderer aren't added until reader is actually read
        Assert.assertEquals(0, ((Set<String>) mockRequest.getAttribute(ILayer.DEPENDENT_FEATURES)).size());
        CopyUtil.copy(reader, writer);
        // dependent features from build renderer should now be in request
        Assert.assertEquals((Set<String>) new HashSet<String>(Arrays.asList(new String[] { "feature1" })),
                (Set<String>) mockRequest.getAttribute(ILayer.DEPENDENT_FEATURES));

    }
}