////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2017 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
////////////////////////////////////////////////////////////////////////////////

package com.puppycrawl.tools.checkstyle;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
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.Matchers.any;
import static org.mockito.Mockito.times;
import static org.powermock.api.mockito.PowerMockito.doNothing;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.verifyStatic;
import static org.powermock.api.mockito.PowerMockito.when;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashSet;
import java.util.Locale;
import java.util.Properties;
import java.util.Set;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import com.google.common.io.BaseEncoding;
import com.google.common.io.ByteStreams;
import com.google.common.io.Closeables;
import com.google.common.io.Flushables;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import com.puppycrawl.tools.checkstyle.api.Configuration;
import com.puppycrawl.tools.checkstyle.utils.CommonUtils;

@RunWith(PowerMockRunner.class)
@PrepareForTest({ PropertyCacheFile.class, ByteStreams.class,
        CommonUtils.class, Closeables.class, Flushables.class})
public class PropertyCacheFileTest extends AbstractPathTestSupport {

    @Rule
    public final TemporaryFolder temporaryFolder = new TemporaryFolder();

    @Override
    protected String getPackageLocation() {
        return "com/puppycrawl/tools/checkstyle/propertycachefile";
    }

    @Test
    public void testCtor() {
        try {
            final Object test = new PropertyCacheFile(null, "");
            fail("exception expected but got " + test);
        }
        catch (IllegalArgumentException ex) {
            assertEquals("Invalid exception message",
                    "config can not be null", ex.getMessage());
        }
        try {
            final Configuration config = new DefaultConfiguration("myName");
            final Object test = new PropertyCacheFile(config, null);
            fail("exception expected but got " + test);
        }
        catch (IllegalArgumentException ex) {
            assertEquals("Invalid exception message",
                    "fileName can not be null", ex.getMessage());
        }
    }

    @Test
    public void testInCache() throws IOException {
        final Configuration config = new DefaultConfiguration("myName");
        final String filePath = temporaryFolder.newFile().getPath();
        final PropertyCacheFile cache = new PropertyCacheFile(config, filePath);
        cache.put("myFile", 1);
        assertTrue("Should return true wnen file is in cache",
                cache.isInCache("myFile", 1));
        assertFalse("Should return false wnen file is not in cache",
                cache.isInCache("myFile", 2));
        assertFalse("Should return false wnen file is not in cache",
                cache.isInCache("myFile1", 1));
    }

    @Test
    public void testResetIfFileDoesNotExist() throws IOException {
        final Configuration config = new DefaultConfiguration("myName");
        final PropertyCacheFile cache = new PropertyCacheFile(config, "fileDoesNotExist.txt");

        cache.load();

        assertNotNull("Config hash key should not be null",
                cache.get(PropertyCacheFile.CONFIG_HASH_KEY));
    }

    @Test
    public void testCloseAndFlushOutputStreamAfterCreatingHashCode() throws IOException {
        mockStatic(Closeables.class);
        doNothing().when(Closeables.class);
        Closeables.close(any(ObjectOutputStream.class), Matchers.eq(false));
        mockStatic(Flushables.class);
        doNothing().when(Flushables.class);
        Flushables.flush(any(ObjectOutputStream.class), Matchers.eq(false));

        final Configuration config = new DefaultConfiguration("myName");
        final PropertyCacheFile cache = new PropertyCacheFile(config, "fileDoesNotExist.txt");
        cache.load();

        verifyStatic(times(1));

        Closeables.close(any(ObjectOutputStream.class), Matchers.eq(false));
        verifyStatic(times(1));
        Flushables.flush(any(ObjectOutputStream.class), Matchers.eq(false));
    }

    @Test
    public void testPopulateDetails() throws IOException {
        mockStatic(Closeables.class);
        doNothing().when(Closeables.class);
        Closeables.closeQuietly(any(FileInputStream.class));

        final Configuration config = new DefaultConfiguration("myName");
        final PropertyCacheFile cache = new PropertyCacheFile(config,
                getPath("InputPropertyCacheFile"));
        cache.load();

        final String hash = cache.get(PropertyCacheFile.CONFIG_HASH_KEY);
        assertNotNull("Config hash key should not be null", hash);
        assertNull("Should return null if key is not in cache", cache.get("key"));

        cache.load();

        assertEquals("Invalid config hash key", hash, cache.get(PropertyCacheFile.CONFIG_HASH_KEY));
        assertEquals("Invalid cache value", "value", cache.get("key"));
        assertNotNull("Config hash key should not be null",
                cache.get(PropertyCacheFile.CONFIG_HASH_KEY));

        verifyStatic(times(2));
        Closeables.closeQuietly(any(FileInputStream.class));
    }

    @Test
    public void testConfigHashOnReset() throws IOException {
        final Configuration config = new DefaultConfiguration("myName");
        final String filePath = temporaryFolder.newFile().getPath();
        final PropertyCacheFile cache = new PropertyCacheFile(config, filePath);

        cache.load();

        final String hash = cache.get(PropertyCacheFile.CONFIG_HASH_KEY);
        assertNotNull("Config hash key should not be null", hash);

        cache.reset();

        assertEquals("Invalid config hash key",
                hash, cache.get(PropertyCacheFile.CONFIG_HASH_KEY));
    }

    @Test
    public void testConfigHashRemainsOnResetExternalResources() throws IOException {
        final Configuration config = new DefaultConfiguration("myName");
        final String filePath = temporaryFolder.newFile().getPath();
        final PropertyCacheFile cache = new PropertyCacheFile(config, filePath);

        // create cache with one file
        cache.load();
        cache.put("myFile", 1);

        final String hash = cache.get(PropertyCacheFile.CONFIG_HASH_KEY);
        assertNotNull("Config hash key should not be null", hash);

        // apply new external resource to clear cache
        final Set<String> resources = new HashSet<>();
        resources.add("dummy");
        cache.putExternalResources(resources);

        assertEquals("Invalid config hash key",
                hash, cache.get(PropertyCacheFile.CONFIG_HASH_KEY));
        assertFalse("Should return false in file is not in cache",
                cache.isInCache("myFile", 1));
    }

    @Test
    public void testExternalResourseIsSavedInCache() throws Exception {
        final Configuration config = new DefaultConfiguration("myName");
        final String filePath = temporaryFolder.newFile().getPath();
        final PropertyCacheFile cache = new PropertyCacheFile(config, filePath);

        cache.load();

        final Set<String> resources = new HashSet<>();
        final String pathToResource = getPath("InputPropertyCacheFileExternal.properties");
        resources.add(pathToResource);
        cache.putExternalResources(resources);

        final MessageDigest digest = MessageDigest.getInstance("SHA-1");
        final URI uri = CommonUtils.getUriByFilename(pathToResource);
        final byte[] input =
                ByteStreams.toByteArray(new BufferedInputStream(uri.toURL().openStream()));
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        try (ObjectOutputStream oos = new ObjectOutputStream(out)) {
            oos.writeObject(input);
        }
        digest.update(out.toByteArray());
        final String expected = BaseEncoding.base16().upperCase().encode(digest.digest());

        assertEquals("Hashes are not equal", expected,
                cache.get("module-resource*?:" + pathToResource));
    }

    /**
     * This SuppressWarning("unchecked") required to suppress
     * "Unchecked generics array creation for varargs parameter" during mock
     * @throws IOException when smth wrong with file creation or cache.load
     */
    @SuppressWarnings("unchecked")
    @Test
    public void testNonExistingResource() throws IOException {
        final Configuration config = new DefaultConfiguration("myName");
        final String filePath = temporaryFolder.newFile().getPath();
        final PropertyCacheFile cache = new PropertyCacheFile(config, filePath);

        // create cache with one file
        cache.load();
        final String myFile = "myFile";
        cache.put(myFile, 1);

        final String hash = cache.get(PropertyCacheFile.CONFIG_HASH_KEY);
        assertNotNull("Config hash key should not be null", hash);

        mockStatic(ByteStreams.class);

        when(ByteStreams.toByteArray(any(BufferedInputStream.class)))
                .thenThrow(IOException.class);

        // apply new external resource to clear cache
        final Set<String> resources = new HashSet<>();
        final String resource = getPath("InputPropertyCacheFile.header");
        resources.add(resource);
        cache.putExternalResources(resources);

        assertFalse("Should return false in file is not in cache",
                cache.isInCache(myFile, 1));
        assertFalse("Should return false in file is not in cache",
                cache.isInCache(resource, 1));
    }

    @Test
    public void testFlushAndCloseCacheFileOutputStream() throws IOException {
        mockStatic(Closeables.class);
        doNothing().when(Closeables.class);
        Closeables.close(any(FileOutputStream.class), Matchers.eq(false));
        mockStatic(Flushables.class);
        doNothing().when(Flushables.class);
        Flushables.flush(any(FileOutputStream.class), Matchers.eq(false));

        final Configuration config = new DefaultConfiguration("myName");
        final PropertyCacheFile cache = new PropertyCacheFile(config,
            temporaryFolder.newFile().getPath());

        cache.put("CheckedFileName.java", System.currentTimeMillis());
        cache.persist();

        verifyStatic(times(1));
        Closeables.close(any(FileOutputStream.class), Matchers.eq(false));
        verifyStatic(times(1));
        Flushables.flush(any(FileOutputStream.class), Matchers.eq(false));
    }

    @Test
    public void testCacheDirectoryDoesNotExistAndShouldBeCreated() throws IOException {
        final Configuration config = new DefaultConfiguration("myName");
        final String filePath = String.format(Locale.getDefault(), "%s%2$stemp%2$scache.temp",
            temporaryFolder.getRoot(), File.separator);
        final PropertyCacheFile cache = new PropertyCacheFile(config, filePath);

        // no exception expected, cache directory should be created
        cache.persist();

        assertTrue("cache exists in directory", new File(filePath).exists());
    }

    @Test
    public void testPathToCacheContainsOnlyFileName() throws IOException {
        final Configuration config = new DefaultConfiguration("myName");
        final String filePath = "temp.cache";
        final PropertyCacheFile cache = new PropertyCacheFile(config, filePath);

        // no exception expected
        cache.persist();
        assertTrue("Cache file does not exist", Files.exists(Paths.get(filePath)));
        Files.delete(Paths.get(filePath));
    }

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

        final Configuration config = new DefaultConfiguration("myName");
        final String filePath = temporaryFolder.newFile().getPath();
        final PropertyCacheFile cache = new PropertyCacheFile(config, filePath);
        cache.put("myFile", 1);
        mockStatic(MessageDigest.class);

        when(MessageDigest.getInstance("SHA-1"))
                .thenThrow(NoSuchAlgorithmException.class);

        final Class<?>[] param = new Class<?>[1];
        param[0] = Serializable.class;
        final Method method =
            PropertyCacheFile.class.getDeclaredMethod("getHashCodeBasedOnObjectContent", param);
        method.setAccessible(true);
        try {
            method.invoke(cache, config);
            fail("InvocationTargetException is expected");
        }
        catch (InvocationTargetException ex) {
            assertTrue("Invalid exception cause",
                    ex.getCause().getCause() instanceof NoSuchAlgorithmException);
            assertEquals("Invalid exception message",
                    "Unable to calculate hashcode.", ex.getCause().getMessage());
        }
    }

    @Test
    public void testPutNonExsistingExternalResourceSameExceptionBetweenRuns() throws Exception {
        final File cacheFile = temporaryFolder.newFile();

        // We mock getUriByFilename method of CommonUtils to garantee that it will
        // throw CheckstyleException with the specific content.
        mockStatic(CommonUtils.class);
        final CheckstyleException mockException =
            new CheckstyleException("Cannot get URL for cache file " + cacheFile.getAbsolutePath());
        when(CommonUtils.getUriByFilename(any(String.class)))
            .thenThrow(mockException);

        // We invoke 'putExternalResources' twice to invalidate cache
        // and have two identical exceptions whith the equal content
        final int numberOfRuns = 2;
        final String[] configHashes = new String[numberOfRuns];
        final String[] externalResourceHashes = new String[numberOfRuns];
        for (int i = 0; i < numberOfRuns; i++) {
            final Configuration config = new DefaultConfiguration("myConfig");
            final PropertyCacheFile cache = new PropertyCacheFile(config, cacheFile.getPath());
            cache.load();

            configHashes[i] = cache.get(PropertyCacheFile.CONFIG_HASH_KEY);
            assertNotNull("Config hash key should not be null", configHashes[i]);

            final Set<String> nonExistingExternalResources = new HashSet<>();
            final String externalResourceFileName = "non_existing_file.xml";
            nonExistingExternalResources.add(externalResourceFileName);
            cache.putExternalResources(nonExistingExternalResources);

            externalResourceHashes[i] = cache.get(PropertyCacheFile.EXTERNAL_RESOURCE_KEY_PREFIX
                    + externalResourceFileName);
            assertNotNull("External resource hashes should not be null",
                    externalResourceHashes[i]);

            cache.persist();

            final Properties cacheDetails = new Properties();
            cacheDetails.load(Files.newBufferedReader(cacheFile.toPath()));

            final int expectedNumberOfObjectsInCacheFile = 2;
            assertEquals("Unexpected number of objects in cache",
                    expectedNumberOfObjectsInCacheFile, cacheDetails.size());
        }

        assertEquals("Invalid config hash", configHashes[0], configHashes[1]);
        assertEquals("Invalid external resource hashes",
                externalResourceHashes[0], externalResourceHashes[1]);
    }

    /**
     * It is OK to have long test method name here as it describes the test purpose.
     * @noinspection InstanceMethodNamingConvention
     */
    @Test
    public void testPutNonExsistingExternalResourceDifferentExceptionsBetweenRuns()
            throws Exception {

        final File cacheFile = temporaryFolder.newFile();

        // We invoke 'putExternalResources' twice to invalidate cache
        // and have two different exceptions with different content.
        final int numberOfRuns = 2;
        final String[] configHashes = new String[numberOfRuns];
        final String[] externalResourceHashes = new String[numberOfRuns];
        for (int i = 0; i < numberOfRuns; i++) {
            final Configuration config = new DefaultConfiguration("myConfig");
            final PropertyCacheFile cache = new PropertyCacheFile(config, cacheFile.getPath());

            // We mock getUriByFilename method of CommonUtils to garantee that it will
            // throw CheckstyleException with the specific content.
            mockStatic(CommonUtils.class);
            final CheckstyleException mockException = new CheckstyleException("Exception #" + i);
            when(CommonUtils.getUriByFilename(any(String.class)))
                .thenThrow(mockException);

            cache.load();

            configHashes[i] = cache.get(PropertyCacheFile.CONFIG_HASH_KEY);
            assertNotNull("Config hash key should not be null", configHashes[i]);

            final Set<String> nonExistingExternalResources = new HashSet<>();
            final String externalResourceFileName = "non_existing_file.xml";
            nonExistingExternalResources.add(externalResourceFileName);
            cache.putExternalResources(nonExistingExternalResources);

            externalResourceHashes[i] = cache.get(PropertyCacheFile.EXTERNAL_RESOURCE_KEY_PREFIX
                    + externalResourceFileName);
            assertNotNull("External resource hashes should not be null",
                    externalResourceHashes[i]);

            cache.persist();

            final Properties cacheDetails = new Properties();
            cacheDetails.load(Files.newBufferedReader(cacheFile.toPath()));

            final int expectedNumberOfObjectsInCacheFile = 2;
            assertEquals("Unexpected number of objects in cache",
                    expectedNumberOfObjectsInCacheFile, cacheDetails.size());
        }

        assertEquals("Invalid config hash", configHashes[0], configHashes[1]);
        assertNotEquals("Invalid external resource hashes",
                externalResourceHashes[0], externalResourceHashes[1]);
    }

    @Test
    public void testChangeInConfig() throws Exception {
        final DefaultConfiguration config = new DefaultConfiguration("myConfig");
        config.addAttribute("attr", "value");

        final File cacheFile = temporaryFolder.newFile();
        final PropertyCacheFile cache = new PropertyCacheFile(config, cacheFile.getPath());
        cache.load();

        final String expectedInitialConfigHash = "91753B970AFDF9F5F3DFA0D258064841949D3C6B";
        final String actualInitialConfigHash = cache.get(PropertyCacheFile.CONFIG_HASH_KEY);
        assertEquals("Invalid config hash", expectedInitialConfigHash, actualInitialConfigHash);

        cache.persist();

        final Properties details = new Properties();
        details.load(Files.newBufferedReader(cacheFile.toPath()));
        assertEquals("Invalid details size", 1, details.size());

        // change in config
        config.addAttribute("newAttr", "newValue");

        final PropertyCacheFile cacheAfterChangeInConfig =
            new PropertyCacheFile(config, cacheFile.getPath());
        cacheAfterChangeInConfig.load();

        final String expectedConfigHashAfterChange = "4CF5EC78955B81D76153ACC2CA6D60CB77FDCB2A";
        final String actualConfigHashAfterChange =
            cacheAfterChangeInConfig.get(PropertyCacheFile.CONFIG_HASH_KEY);
        assertEquals("Invalid config hash",
                expectedConfigHashAfterChange, actualConfigHashAfterChange);

        cacheAfterChangeInConfig.persist();

        final Properties detailsAfterChangeInConfig = new Properties();
        detailsAfterChangeInConfig.load(Files.newBufferedReader(cacheFile.toPath()));
        assertEquals("Invalid cache size", 1, detailsAfterChangeInConfig.size());
    }
}
