Class DiffRepository


  • public class DiffRepository
    extends java.lang.Object
    A collection of resources used by tests.

    Loads files containing test input and output into memory. If there are differences, writes out a log file containing the actual output.

    Typical usage is as follows. A test case class defines a method

    
     package com.acme.test;
      
     public class MyTest extends TestCase {
       public DiffRepository getDiffRepos() {
         return DiffRepository.lookup(MyTest.class);
       }
      
       @Test public void testToUpper() {
         getDiffRepos().assertEquals("${result}", "${string}");
       }
      
       @Test public void testToLower() {
         getDiffRepos().assertEquals("Multi-line\nstring", "${string}");
       }
     }
     

    There is an accompanying reference file named after the class, src/test/resources/com/acme/test/MyTest.xml:

    
     <Root>
         <TestCase name="testToUpper">
             <Resource name="string">
                 <![CDATA[String to be converted to upper case]]>
             </Resource>
             <Resource name="result">
                 <![CDATA[STRING TO BE CONVERTED TO UPPER CASE]]>
             </Resource>
         </TestCase>
         <TestCase name="testToLower">
             <Resource name="result">
                 <![CDATA[multi-line
     string]]>
             </Resource>
         </TestCase>
     </Root>
    
     

    If any of the test cases fails, a log file is generated, called target/surefire/com/acme/test/MyTest.xml, containing the actual output.

    (Maven sometimes removes this file; if it is not present, run maven with an extra -X flag. See [SUREFIRE-846] for details.)

    The log file is otherwise identical to the reference log, so once the log file has been verified, it can simply be copied over to become the new reference log:

    cp target/surefire/com/acme/test/MyTest.xml src/test/resources/com/acme/test/MyTest.xml

    If a resource or test case does not exist, DiffRepository creates them in the log file. Because DiffRepository is so forgiving, it is very easy to create new tests and test cases.

    The lookup(java.lang.Class) method ensures that all test cases share the same instance of the repository. This is important more than one one test case fails. The shared instance ensures that the generated target/surefire/com/acme/test/MyTest.xml file contains the actual for both test cases.

    • Nested Class Summary

      Nested Classes 
      Modifier and Type Class Description
      static interface  DiffRepository.Filter
      Callback to filter strings before returning them.
    • Method Summary

      All Methods Static Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      void amend​(java.lang.String expected, java.lang.String actual)  
      void assertEquals​(java.lang.String tag, java.lang.String expected, java.lang.String actual)  
      java.lang.String expand​(java.lang.String tag, java.lang.String text)
      Expands a string containing one or more variables.
      private static java.net.URL findFile​(java.lang.Class clazz, java.lang.String suffix)  
      private void flushDoc()
      Flushes the reference document to the file system.
      private java.lang.String get​(java.lang.String testCaseName, java.lang.String resourceName)
      Returns a given resource from a given test case.
      private java.lang.String getCurrentTestCaseName​(boolean fail)
      Returns the name of the current test case by looking up the call stack for a method whose name starts with "test", for example "testFoo".
      private static org.w3c.dom.Element getResourceElement​(org.w3c.dom.Element testCaseElement, java.lang.String resourceName)
      Returns a given resource from a given test case.
      private static org.w3c.dom.Element getResourceElement​(org.w3c.dom.Element testCaseElement, java.lang.String resourceName, boolean killYoungerSiblings)
      Returns a given resource from a given test case.
      private org.w3c.dom.Element getTestCaseElement​(java.lang.String testCaseName, boolean checkOverride, java.util.List<org.apache.calcite.util.Pair<java.lang.String,​org.w3c.dom.Element>> elements)
      Returns the <TestCase> element corresponding to the current test case.
      private static java.lang.String getText​(org.w3c.dom.Element element)
      Returns the text under an element.
      private static boolean isWhitespace​(java.lang.String text)  
      static DiffRepository lookup​(java.lang.Class clazz)
      Finds the repository instance for a given class, with no base repository or filter.
      static DiffRepository lookup​(java.lang.Class clazz, DiffRepository baseRepository)
      Finds the repository instance for a given class and inheriting from a given repository.
      static DiffRepository lookup​(java.lang.Class clazz, DiffRepository baseRepository, DiffRepository.Filter filter)
      Finds the repository instance for a given class.
      private org.w3c.dom.Node ref​(java.lang.String testCaseName, java.util.List<org.apache.calcite.util.Pair<java.lang.String,​org.w3c.dom.Element>> map)  
      private static void removeAllChildren​(org.w3c.dom.Element element)  
      void set​(java.lang.String resourceName, java.lang.String value)
      Sets the value of a given resource of the current test case.
      private void update​(java.lang.String testCaseName, java.lang.String resourceName, java.lang.String value)
      Creates a new document with a given resource.
      private static void write​(org.w3c.dom.Document doc, java.io.Writer w, int indent)
      Serializes an XML document as text.
      private static void writeNode​(org.w3c.dom.Node node, org.apache.calcite.util.XmlOutput out)  
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Field Detail

      • TEST_CASE_NAME_ATTR

        private static final java.lang.String TEST_CASE_NAME_ATTR
        See Also:
        Constant Field Values
      • TEST_CASE_OVERRIDES_ATTR

        private static final java.lang.String TEST_CASE_OVERRIDES_ATTR
        See Also:
        Constant Field Values
      • RESOURCE_NAME_ATTR

        private static final java.lang.String RESOURCE_NAME_ATTR
        See Also:
        Constant Field Values
      • MAP_CLASS_TO_REPOSITORY

        private static final java.util.Map<java.lang.Class,​DiffRepository> MAP_CLASS_TO_REPOSITORY
        Holds one diff-repository per class. It is necessary for all test cases in the same class to share the same diff-repository: if the repository gets loaded once per test case, then only one diff is recorded.
      • indent

        private final int indent
      • doc

        private org.w3c.dom.Document doc
      • root

        private final org.w3c.dom.Element root
      • logFile

        private final java.io.File logFile
    • Constructor Detail

      • DiffRepository

        private DiffRepository​(java.net.URL refFile,
                               java.io.File logFile,
                               DiffRepository baseRepository,
                               DiffRepository.Filter filter)
        Creates a DiffRepository.
        Parameters:
        refFile - Reference file
        logFile - Log file
        baseRepository - Parent repository or null
        filter - Filter or null
    • Method Detail

      • findFile

        private static java.net.URL findFile​(java.lang.Class clazz,
                                             java.lang.String suffix)
      • expand

        public java.lang.String expand​(java.lang.String tag,
                                       java.lang.String text)
        Expands a string containing one or more variables. (Currently only works if there is one variable.)
      • set

        public void set​(java.lang.String resourceName,
                        java.lang.String value)
        Sets the value of a given resource of the current test case.
        Parameters:
        resourceName - Name of the resource, e.g. "sql"
        value - Value of the resource
      • amend

        public void amend​(java.lang.String expected,
                          java.lang.String actual)
      • get

        private java.lang.String get​(java.lang.String testCaseName,
                                     java.lang.String resourceName)
        Returns a given resource from a given test case.
        Parameters:
        testCaseName - Name of test case, e.g. "testFoo"
        resourceName - Name of resource, e.g. "sql", "plan"
        Returns:
        The value of the resource, or null if not found
      • getText

        private static java.lang.String getText​(org.w3c.dom.Element element)
        Returns the text under an element.
      • getTestCaseElement

        private org.w3c.dom.Element getTestCaseElement​(java.lang.String testCaseName,
                                                       boolean checkOverride,
                                                       java.util.List<org.apache.calcite.util.Pair<java.lang.String,​org.w3c.dom.Element>> elements)
        Returns the <TestCase> element corresponding to the current test case.
        Parameters:
        testCaseName - Name of test case
        checkOverride - Make sure that if an element overrides an element in a base repository, it has overrides="true"
        Returns:
        TestCase element, or null if not found
      • getCurrentTestCaseName

        private java.lang.String getCurrentTestCaseName​(boolean fail)
        Returns the name of the current test case by looking up the call stack for a method whose name starts with "test", for example "testFoo".
        Parameters:
        fail - Whether to fail if no method is found
        Returns:
        Name of current test case, or null if not found
      • assertEquals

        public void assertEquals​(java.lang.String tag,
                                 java.lang.String expected,
                                 java.lang.String actual)
      • update

        private void update​(java.lang.String testCaseName,
                            java.lang.String resourceName,
                            java.lang.String value)
        Creates a new document with a given resource.

        This method is synchronized, in case two threads are running test cases of this test at the same time.

        Parameters:
        testCaseName - Test case name
        resourceName - Resource name
        value - New value of resource
      • ref

        private org.w3c.dom.Node ref​(java.lang.String testCaseName,
                                     java.util.List<org.apache.calcite.util.Pair<java.lang.String,​org.w3c.dom.Element>> map)
      • flushDoc

        private void flushDoc()
        Flushes the reference document to the file system.
      • getResourceElement

        private static org.w3c.dom.Element getResourceElement​(org.w3c.dom.Element testCaseElement,
                                                              java.lang.String resourceName)
        Returns a given resource from a given test case.
        Parameters:
        testCaseElement - The enclosing TestCase element, e.g. <TestCase name="testFoo">.
        resourceName - Name of resource, e.g. "sql", "plan"
        Returns:
        The value of the resource, or null if not found
      • getResourceElement

        private static org.w3c.dom.Element getResourceElement​(org.w3c.dom.Element testCaseElement,
                                                              java.lang.String resourceName,
                                                              boolean killYoungerSiblings)
        Returns a given resource from a given test case.
        Parameters:
        testCaseElement - The enclosing TestCase element, e.g. <TestCase name="testFoo">.
        resourceName - Name of resource, e.g. "sql", "plan"
        killYoungerSiblings - Whether to remove resources with the same name and the same parent that are eclipsed
        Returns:
        The value of the resource, or null if not found
      • removeAllChildren

        private static void removeAllChildren​(org.w3c.dom.Element element)
      • write

        private static void write​(org.w3c.dom.Document doc,
                                  java.io.Writer w,
                                  int indent)
        Serializes an XML document as text.

        FIXME: I'm sure there's a library call to do this, but I'm danged if I can find it. -- jhyde, 2006/2/9.

      • writeNode

        private static void writeNode​(org.w3c.dom.Node node,
                                      org.apache.calcite.util.XmlOutput out)
      • isWhitespace

        private static boolean isWhitespace​(java.lang.String text)
      • lookup

        public static DiffRepository lookup​(java.lang.Class clazz)
        Finds the repository instance for a given class, with no base repository or filter.
        Parameters:
        clazz - Test case class
        Returns:
        The diff repository shared between test cases in this class.
      • lookup

        public static DiffRepository lookup​(java.lang.Class clazz,
                                            DiffRepository baseRepository)
        Finds the repository instance for a given class and inheriting from a given repository.
        Parameters:
        clazz - Test case class
        baseRepository - Base class of test class
        Returns:
        The diff repository shared between test cases in this class.
      • lookup

        public static DiffRepository lookup​(java.lang.Class clazz,
                                            DiffRepository baseRepository,
                                            DiffRepository.Filter filter)
        Finds the repository instance for a given class.

        It is important that all test cases in a class share the same repository instance. This ensures that, if two or more test cases fail, the log file will contains the actual results of both test cases.

        The baseRepository parameter is useful if the test is an extension to a previous test. If the test class has a base class which also has a repository, specify the repository here. DiffRepository will look for resources in the base class if it cannot find them in this repository. If test resources from test cases in the base class are missing or incorrect, it will not write them to the log file -- you probably need to fix the base test.

        Use the filter parameter if you expect the test to return results slightly different than in the repository. This happens if the behavior of a derived test is slightly different than a base test. If you do not specify a filter, no filtering will happen.

        Parameters:
        clazz - Test case class
        baseRepository - Base repository
        filter - Filters each string returned by the repository
        Returns:
        The diff repository shared between test cases in this class.