Add unit tests for Config.java.
authorChris Jaekl <cejaekl@yahoo.com>
Sat, 31 Oct 2015 03:06:09 +0000 (12:06 +0900)
committerChris Jaekl <cejaekl@yahoo.com>
Sat, 31 Oct 2015 03:06:09 +0000 (12:06 +0900)
prod/net/jaekl/cfb/Config.java
prod/net/jaekl/qd/util/FileIO.java [new file with mode: 0644]
test/net/jaekl/cfb/ConfigTest.java
test/net/jaekl/qd/util/FileIOMock.java [new file with mode: 0644]
test/net/jaekl/qd/util/FileMock.java [new file with mode: 0644]

index 8bb401dc4ebdb48d34f89290e3d030bda145b09f..8aa423419ef74ab08fee0c9764124d9215ba5b72 100644 (file)
@@ -1,14 +1,16 @@
 package net.jaekl.cfb;
 
 import java.io.File;
 package net.jaekl.cfb;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Properties;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Properties;
 
+import net.jaekl.qd.util.FileIO;
+
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.GnuParser;
 import org.apache.commons.cli.Options;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.GnuParser;
 import org.apache.commons.cli.Options;
@@ -65,15 +67,15 @@ public class Config {
        public void readFile(File configProperties) throws IOException
        {
                Properties props = new Properties();
        public void readFile(File configProperties) throws IOException
        {
                Properties props = new Properties();
-               FileInputStream fis = null;
+               InputStream is = null;
                
                try {
                
                try {
-                       fis = new FileInputStream(configProperties);
-                       props.load(fis);
+                       is = FileIO.getInst().openInput(configProperties);
+                       props.load(is);
                }
                finally {
                }
                finally {
-                       if (null != fis) {
-                               fis.close();
+                       if (null != is) {
+                               is.close();
                        }
                }
                
                        }
                }
                
diff --git a/prod/net/jaekl/qd/util/FileIO.java b/prod/net/jaekl/qd/util/FileIO.java
new file mode 100644 (file)
index 0000000..450d6ed
--- /dev/null
@@ -0,0 +1,42 @@
+package net.jaekl.qd.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+// Dispatch File Input/Output operations from a singleton
+// This makes it possible to intercept file reads and writes
+// during unit testing, and replace them with mock operations.
+
+public class FileIO {
+       // Note:  need volatile to implement double-checked locking in getInst()
+       static volatile FileIO m_inst = null;
+       
+       FileIO() { ; }
+       
+       public static FileIO getInst() { 
+               FileIO result = m_inst;
+               if (null == result) {
+                       synchronized(FileIO.class) {
+                               if (null == m_inst) {
+                                       m_inst = new FileIO();
+                               }
+                               result = m_inst;
+                       }
+               }
+               return result;
+       }
+       
+       public InputStream openInput(File file) throws FileNotFoundException 
+       {
+               return new FileInputStream(file);
+       }
+       
+       public OutputStream openOutput(File file) throws FileNotFoundException 
+       {
+               return new FileOutputStream(file);
+       }
+}
index 3fafe87bf0c668cefae6a5db021bd958ee93ef0e..e7ca44c87025517f864700db538861ec5b08ad5f 100644 (file)
@@ -1,24 +1,72 @@
 package net.jaekl.cfb;
 
 package net.jaekl.cfb;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 
+import java.io.IOException;
+import java.util.List;
+
+import net.jaekl.qd.util.FileIOMock;
+import net.jaekl.qd.util.FileMock;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
 public class ConfigTest {
 import org.junit.Test;
 
 public class ConfigTest {
+       private static final String CHRIS = "chris@localhost";
+       private static final String HUDSON = "hudson@jenkins.org";
+       private static final String MAIL_FROM = "findbugs@jaekl.net";
+       private static final String MAIL_TO = CHRIS + "," + HUDSON;
+       private static final String LOCALHOST = "localhost";
 
        private static final String SAMPLE1 = 
                          "; Path (relative or absolute) to the FINDBUGS_HOME, i.e., where FindBugs is installed\n"
                        + "FindBugsHome=../findbugs-3.0.1/\n"
                        + "; List (comma-separated) of email addresses to which notifications should be sent\n"
 
        private static final String SAMPLE1 = 
                          "; Path (relative or absolute) to the FINDBUGS_HOME, i.e., where FindBugs is installed\n"
                        + "FindBugsHome=../findbugs-3.0.1/\n"
                        + "; List (comma-separated) of email addresses to which notifications should be sent\n"
-                       + "notify=chris@localhost\n"
+                       + "notify=" + MAIL_TO + "\n"
                        + "\n"
                        + "; Mail server setup\n"
                        + "\n"
                        + "; Mail server setup\n"
-                       + "mail.smtp.host=localhost\n"
-                       + "mail.from=findbugs@localhost\n";
+                       + "mail.smtp.host=" + LOCALHOST + "\n"
+                       + "mail.from=" + MAIL_FROM + "\n";
 
 
+       @BeforeClass 
+       public static void beforeClass() {
+               FileIOMock.mock_setInstance();
+       }
+       
+       @AfterClass
+       public static void afterClass() {
+               FileIOMock.mock_clearInstance();
+       }
+       
        @Test
        @Test
-       public void testReadFile() {
-               // TODO:  wrap file access so that we can test this
+       public void testReadFile() throws IOException {
+               Config config = new Config();
+               
+               FileMock fm = new FileMock("config.properties");
+               fm.mock_setContent(SAMPLE1);
+               
+               config.readFile(fm);
+               
+               assertEquals(MAIL_FROM, config.getMailFrom());
+               assertEquals(LOCALHOST, config.getMailSmtpHost());
+               
+               List<String> notify = config.getNotify();
+               assertTrue(notify.contains(CHRIS));
+               assertTrue(notify.contains(HUDSON));
+       }
+       
+       @Test
+       public void testReadEmptyFile() throws IOException {
+               Config config = new Config();
+               FileMock fm = new FileMock("empty.properties");
+               fm.mock_setContent("");
+               
+               config.readFile(fm);
+               
+               assertEquals("findbugs@localhost", config.getMailFrom());
+               assertEquals("localhost", config.getMailSmtpHost());
+               assertEquals(0, config.getNotify().size());
        }
        }
-
 }
 }
diff --git a/test/net/jaekl/qd/util/FileIOMock.java b/test/net/jaekl/qd/util/FileIOMock.java
new file mode 100644 (file)
index 0000000..adfadf6
--- /dev/null
@@ -0,0 +1,39 @@
+package net.jaekl.qd.util;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class FileIOMock extends FileIO {
+       private FileIOMock() { ; }
+       
+       public static void mock_setInstance() {
+               synchronized(FileIO.class) {
+                       m_inst = new FileIOMock();
+               }
+       }
+       
+       public static void mock_clearInstance() {
+               synchronized(FileIO.class) {
+                       m_inst = null;
+               }
+       }
+       
+       @Override
+       public InputStream openInput(File file) {
+               if (file instanceof FileMock) {
+                       FileMock fm = (FileMock)file;
+                       return fm.mock_openInput();
+               }
+               throw new IllegalArgumentException("Expected FileMock, not File");
+       }
+       
+       @Override
+       public OutputStream openOutput(File file) {
+               if (file instanceof FileMock) {
+                       FileMock fm = (FileMock)file;
+                       return fm.mock_openOutput();
+               }
+               throw new IllegalArgumentException("Expected FileMock, not File");
+       }
+}
diff --git a/test/net/jaekl/qd/util/FileMock.java b/test/net/jaekl/qd/util/FileMock.java
new file mode 100644 (file)
index 0000000..a886f4c
--- /dev/null
@@ -0,0 +1,52 @@
+package net.jaekl.qd.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.nio.charset.Charset;
+
+public class FileMock extends File {
+       private static final long serialVersionUID = 1L;
+       public static final String UTF_8 = "UTF-8";
+       
+       private ByteArrayInputStream m_bais;
+       private ByteArrayOutputStream m_baos;
+       private byte[] m_content;
+
+       public FileMock(String fileName) {
+               super(fileName);
+               
+               m_bais = null;
+               m_baos = null;
+               m_content = new byte[0];
+       }
+       
+       public ByteArrayInputStream mock_openInput() {
+               m_bais = new ByteArrayInputStream(mock_getContent());
+               return m_bais;
+       }
+       
+       public ByteArrayOutputStream mock_openOutput() {
+               m_baos = new ByteArrayOutputStream();
+               return m_baos;
+       }
+       
+       public void mock_setContent(byte[] content) {
+               m_content = content.clone();
+       }
+       
+       public void mock_setContent(String content, Charset charset) {
+               m_content = content.getBytes(charset);
+       }
+       
+       public void mock_setContent(String content) {
+               mock_setContent(content, Charset.forName(UTF_8));
+       }
+       
+       public byte[] mock_getContent() {
+               if (null != m_baos) {
+                       m_content = m_baos.toByteArray();
+               }
+               return m_content.clone();
+       }
+}