/*
 * Copyright (C) 2013 salesforce.com, inc.
 *
 * 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 org.auraframework.impl.source.file;

import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.util.Set;

import org.auraframework.def.ApplicationDef;
import org.auraframework.def.ComponentDef;
import org.auraframework.def.DefDescriptor;
import org.auraframework.def.DescriptorFilter;
import org.auraframework.def.EventDef;
import org.auraframework.impl.AuraImplTestCase;
import org.auraframework.impl.system.DefDescriptorImpl;
import org.auraframework.impl.util.AuraImplFiles;
import org.auraframework.system.Parser.Format;
import org.auraframework.system.Source;
import org.auraframework.throwable.AuraRuntimeException;

public class FileSourceLoaderTest extends AuraImplTestCase {

    public FileSourceLoaderTest(String name) {
        super(name);
    }

    @Override
    public void setUp() throws Exception {
        super.setUp();
    }

    @Override
    public void runTest() throws Throwable {
        // filesystem tests are only good if loading from filesystem
        if (AuraImplFiles.TestComponents.asFile().exists()) {
            super.runTest();
        }
    }

    public void testFileSourceLoaderSanity() {
        assertNotNull(new FileSourceLoader(AuraImplFiles.TestComponents.asFile()));
    }

    public void testFileSourceLoaderWithNonExistentFile() {
        try {
            new FileSourceLoader(new File("this_probably_doesnt_exist"));
            fail("Should have thrown AuraException(Base directory does not exist)");
        } catch (AuraRuntimeException e) {
        }
    }

    public void testFileSourceLoaderWithNullFile() {
        try {
            new FileSourceLoader(null);
            fail("Should have thrown AuraException(Base directory does not exist)");
        } catch (AuraRuntimeException e) {
        }

    }

    public void testGetComponentSource() {
        FileSourceLoader loader = new FileSourceLoader(AuraImplFiles.TestComponents.asFile());
        DefDescriptor<ComponentDef> descriptor = DefDescriptorImpl.getInstance("test:parent", ComponentDef.class);
        Source<?> src = loader.getSource(descriptor);
        assertNotNull(src);
        assertEquals(Format.XML, src.getFormat());
        assertEquals(new File(AuraImplFiles.TestComponents.asFile(), "test" + File.separator + "parent"
                + File.separator + "parent.cmp").lastModified(), src.getLastModified());
        assertTrue(src.getSystemId().endsWith("parent.cmp"));
        Reader reader = null;
        try {
            reader = src.getHashingReader();
            assertNotNull(reader);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                    fail("Did not get an exception for not reading the entire file");
                } catch (IllegalStateException ise) {
                    // expected, we didn't read the file.
                } catch (IOException e) {
                    fail(e.getMessage());
                }
            }
        }

        DefDescriptor<ComponentDef> nonDescriptor = DefDescriptorImpl.getInstance("test:nonExistent",
                ComponentDef.class);

        assertFalse(loader.getSource(nonDescriptor).exists());

    }

    public void testGetEventSource() {
        FileSourceLoader loader = new FileSourceLoader(AuraImplFiles.TestComponents.asFile());
        DefDescriptor<EventDef> descriptor = DefDescriptorImpl.getInstance("test:anevent", EventDef.class);
        Source<EventDef> src = loader.getSource(descriptor);
        assertNotNull(src);
        assertEquals(Format.XML, src.getFormat());
        assertEquals(new File(AuraImplFiles.TestComponents.asFile(), "test" + File.separator + "anevent"
                + File.separator + "anevent.evt").lastModified(), src.getLastModified());
        assertTrue(src.getSystemId().endsWith("anevent.evt"));
        Reader reader = null;
        try {
            reader = src.getHashingReader();
            assertNotNull(reader);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                    fail("Did not get an exception for not reading the entire file");
                } catch (IllegalStateException ise) {
                    // expected, we didn't read the file.
                } catch (IOException e) {
                    fail(e.getMessage());
                }
            }
        }

        DefDescriptor<EventDef> nonDescriptor = DefDescriptorImpl.getInstance("test:nonExistentEvent", EventDef.class);
        assertFalse(loader.getSource(nonDescriptor).exists());

    }

    public void testGetNamespaces() {
        FileSourceLoader loader = new FileSourceLoader(AuraImplFiles.TestComponents.asFile());
        Set<String> namespaces = loader.getNamespaces();
        assertTrue(namespaces.contains("test"));
        assertTrue(namespaces.contains("preloadTest"));
        assertTrue(namespaces.contains("setAttributesTest"));
    }

    public void testFindRegex() {
        FileSourceLoader loader = new FileSourceLoader(AuraImplFiles.TestComponents.asFile());
        Set<DefDescriptor<?>> found;

        found = loader.find(new DescriptorFilter("markup://test:extendsParent"));
        assertEquals("Should have found a single component", 1, found.size());
        assertTrue(found.contains(DefDescriptorImpl.getInstance("markup://test:extendsParent", ComponentDef.class)));

        // Number of results can change if files modified so just check at least
        // 2 results from wildcard search since
        // components are more likely to be added than deleted.
        found = loader.find(new DescriptorFilter("markup://test:style*"));
        assertTrue("Should have found multiple components", found.size() > 1);
        assertTrue(found.contains(DefDescriptorImpl.getInstance("markup://test:styleTestTemplate", ComponentDef.class)));
        assertTrue(found.contains(DefDescriptorImpl.getInstance("markup://test:styleTest", ApplicationDef.class)));

        found = loader.find(new DescriptorFilter("markup://test:doesntexist"));
        assertEquals("Should not have found any components", 0, found.size());
    }
}

@@ -2128,32 +2128,128 @@
 eException e) %7B%0A
+        %09checkExceptionRegex(e, AuraRuntimeException.class, %22Base directory.*.does not exist%22);%0A
         %7D%0A    %7D%0A
@@ -2234,32 +2234,32 @@
 st%22);%0A        %7D%0A
-
     %7D%0A%0A    publi
@@ -2476,32 +2476,128 @@
 eException e) %7B%0A
+        %09checkExceptionRegex(e, AuraRuntimeException.class, %22Base directory.*.does not exist%22);%0A
         %7D%0A%0A    %7D
@@ -3623,36 +3623,33 @@
                 
-    
+%09
 // expected, we 
@@ -3662,32 +3662,159 @@
  read the file.%0A
+                %09checkExceptionFull(ise,IllegalStateException.class,%22Closed a hashing file without reading the entire thing%22);%0A
                 
@@ -5143,32 +5143,32 @@
 xception ise) %7B%0A
-
                 
@@ -5201,32 +5201,159 @@
  read the file.%0A
+                %09checkExceptionFull(ise,IllegalStateException.class,%22Closed a hashing file without reading the entire thing%22);%0A
                 

update test for W-2033411 @rev tbliss@ @bug W-2033411@