{-# LANGUAGE OverloadedLists #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} module CSVImport.ImportHelperTurtleTests where import Control.Concurrent.STM import Data.Either import qualified Data.Map.Strict as Map import qualified Data.Text as T import Hledger.Flow.Common import Hledger.Flow.Import.ImportHelpersTurtle (allYearIncludeFiles, extractImportDirs, groupIncludeFiles, toIncludeFiles, toIncludeLine, yearsIncludeMap) import Hledger.Flow.Import.Types (ImportDirs (..), TurtleFileBundle) import Hledger.Flow.PathHelpers (TurtlePath) import Path import Test.HUnit import TestHelpers (defaultOpts) import TestHelpersTurtle import Turtle groupedJaneBogart :: TurtleFileBundle groupedJaneBogart = [ ( "./import/jane/bogartbank/checking/2018-include.journal", ["import/jane/bogartbank/checking/3-journal/2018/2018-12-30.journal"] ), ( "./import/jane/bogartbank/checking/2019-include.journal", ["import/jane/bogartbank/checking/3-journal/2019/2019-01-30.journal"] ), ( "./import/jane/bogartbank/savings/2017-include.journal", ["import/jane/bogartbank/savings/3-journal/2017/2017-12-30.journal"] ), ( "./import/jane/bogartbank/savings/2018-include.journal", ["import/jane/bogartbank/savings/3-journal/2018/2018-01-30.journal"] ) ] groupedJaneOther :: TurtleFileBundle groupedJaneOther = [ ( "./import/jane/otherbank/creditcard/2017-include.journal", ["import/jane/otherbank/creditcard/3-journal/2017/2017-12-30.journal"] ), ( "./import/jane/otherbank/creditcard/2018-include.journal", ["import/jane/otherbank/creditcard/3-journal/2018/2018-01-30.journal"] ), ( "./import/jane/otherbank/investments/2018-include.journal", ["import/jane/otherbank/investments/3-journal/2018/2018-12-30.journal"] ), ( "./import/jane/otherbank/investments/2019-include.journal", ["import/jane/otherbank/investments/3-journal/2019/2019-01-30.journal"] ) ] groupedJohnBogart :: TurtleFileBundle groupedJohnBogart = [ ( "./import/john/bogartbank/checking/2018-include.journal", [ "import/john/bogartbank/checking/3-journal/2018/2018-11-30.journal", "import/john/bogartbank/checking/3-journal/2018/2018-10-30.journal", "import/john/bogartbank/checking/3-journal/2018/2018-12-30.journal" ] ), ( "./import/john/bogartbank/checking/2019-include.journal", [ "import/john/bogartbank/checking/3-journal/2019/2019-01-30.journal", "import/john/bogartbank/checking/3-journal/2019/2019-02-30.journal" ] ), ( "./import/john/bogartbank/savings/2017-include.journal", [ "import/john/bogartbank/savings/3-journal/2017/2017-11-30.journal", "import/john/bogartbank/savings/3-journal/2017/2017-12-30.journal" ] ), ( "./import/john/bogartbank/savings/2018-include.journal", [ "import/john/bogartbank/savings/3-journal/2018/2018-02-30.journal", "import/john/bogartbank/savings/3-journal/2018/2018-01-30.journal" ] ) ] groupedJohnOther :: TurtleFileBundle groupedJohnOther = [ ( "./import/john/otherbank/creditcard/2017-include.journal", ["import/john/otherbank/creditcard/3-journal/2017/2017-12-30.journal"] ), ( "./import/john/otherbank/creditcard/2018-include.journal", ["import/john/otherbank/creditcard/3-journal/2018/2018-01-30.journal"] ), ( "./import/john/otherbank/investments/2018-include.journal", ["import/john/otherbank/investments/3-journal/2018/2018-12-30.journal"] ), ( "./import/john/otherbank/investments/2019-include.journal", ["import/john/otherbank/investments/3-journal/2019/2019-01-30.journal"] ) ] groupedIncludeFiles :: TurtleFileBundle groupedIncludeFiles = groupedJaneBogart <> groupedJaneOther <> groupedJohnBogart <> groupedJohnOther testYearsIncludeMap :: Test testYearsIncludeMap = TestCase ( do let maps = allYearIncludeFiles groupedJohnOther let yearGrouping = [ ( "./import/john/otherbank/creditcard/all-years.journal", [ "./import/john/otherbank/creditcard/2017-include.journal", "./import/john/otherbank/creditcard/2018-include.journal" ] ), ( "./import/john/otherbank/investments/all-years.journal", [ "./import/john/otherbank/investments/2018-include.journal", "./import/john/otherbank/investments/2019-include.journal" ] ) ] let expected = (groupedJohnOther, yearGrouping) assertEqual "An augmented map with grouped years per level added" expected maps ) testYearsIncludeGrouping :: Test testYearsIncludeGrouping = TestCase ( do let yearsMap = yearsIncludeMap (Map.keys groupedJohnOther) let expected = [ ( "./import/john/otherbank/creditcard/all-years.journal", [ "./import/john/otherbank/creditcard/2017-include.journal", "./import/john/otherbank/creditcard/2018-include.journal" ] ), ( "./import/john/otherbank/investments/all-years.journal", [ "./import/john/otherbank/investments/2018-include.journal", "./import/john/otherbank/investments/2019-include.journal" ] ) ] assertEqual "A basic map with grouped years per level" expected yearsMap ) testGroupIncludeFilesTinySet :: Test testGroupIncludeFilesTinySet = TestCase ( do let journals1 = ["import/jane/bogartbank/savings/3-journals/2017/2017-12-30.journal"] let expected1 = [("./import/jane/bogartbank/savings/2017-include.journal", journals1)] :: TurtleFileBundle let expectedAllYears1 = [("./import/jane/bogartbank/savings/all-years.journal", ["./import/jane/bogartbank/savings/2017-include.journal"])] let (group1, allYears1) = groupIncludeFiles journals1 assertEqual "groupIncludeFiles small allYears 1" expectedAllYears1 allYears1 assertEqual "groupIncludeFiles small set 1" expected1 group1 journals2 <- case Map.keys expected1 of (k : _) -> return [k] [] -> assertFailure "Expected non-empty include map for journals2" let expected2 = [("./import/jane/bogartbank/2017-include.journal", journals2)] :: TurtleFileBundle let expectedAllYears2 = [("./import/jane/bogartbank/all-years.journal", ["./import/jane/bogartbank/2017-include.journal"])] let (group2, allYears2) = groupIncludeFiles journals2 assertEqual "groupIncludeFiles small allYears 2" expectedAllYears2 allYears2 assertEqual "groupIncludeFiles small set 2" expected2 group2 journals3 <- case Map.keys expected2 of (k : _) -> return [k] [] -> assertFailure "Expected non-empty include map for journals3" let expected3 = [("./import/jane/2017-include.journal", journals3)] :: TurtleFileBundle let expectedAllYears3 = [("./import/jane/all-years.journal", ["./import/jane/2017-include.journal"])] let (group3, allYears3) = groupIncludeFiles journals3 assertEqual "groupIncludeFiles small allYears 3" expectedAllYears3 allYears3 assertEqual "groupIncludeFiles small set 3" expected3 group3 ) testGroupIncludeFilesSmallSet :: Test testGroupIncludeFilesSmallSet = TestCase ( do let (group1, allYears1) = groupIncludeFiles $ toJournals inputJaneBogart let expectedAllYears1 = [ ( "./import/jane/bogartbank/checking/all-years.journal", [ "./import/jane/bogartbank/checking/2018-include.journal", "./import/jane/bogartbank/checking/2019-include.journal" ] ), ( "./import/jane/bogartbank/savings/all-years.journal", [ "./import/jane/bogartbank/savings/2017-include.journal", "./import/jane/bogartbank/savings/2018-include.journal" ] ) ] assertEqual "groupIncludeFiles Jane AllYears 1" expectedAllYears1 allYears1 assertEqual "groupIncludeFiles Jane 1" groupedJaneBogart group1 let (group2, allYears2) = groupIncludeFiles (Map.keys group1) let expectedAllYears2 = [ ( "./import/jane/bogartbank/all-years.journal", [ "./import/jane/bogartbank/2017-include.journal", "./import/jane/bogartbank/2018-include.journal", "./import/jane/bogartbank/2019-include.journal" ] ) ] assertEqual "groupIncludeFiles Jane AllYears 2" expectedAllYears2 allYears2 let expectedGroup2 = [ ( "./import/jane/bogartbank/2017-include.journal", ["./import/jane/bogartbank/savings/2017-include.journal"] ), ( "./import/jane/bogartbank/2018-include.journal", [ "./import/jane/bogartbank/checking/2018-include.journal", "./import/jane/bogartbank/savings/2018-include.journal" ] ), ( "./import/jane/bogartbank/2019-include.journal", ["./import/jane/bogartbank/checking/2019-include.journal"] ) ] assertEqual "groupIncludeFiles Jane 2" expectedGroup2 group2 let (group3, allYears3) = groupIncludeFiles (Map.keys group2) let expectedAllYears3 = [ ( "./import/jane/all-years.journal", [ "./import/jane/2017-include.journal", "./import/jane/2018-include.journal", "./import/jane/2019-include.journal" ] ) ] assertEqual "groupIncludeFiles Jane AllYears 3" expectedAllYears3 allYears3 let expectedGroup3 = [ ( "./import/jane/2017-include.journal", ["./import/jane/bogartbank/2017-include.journal"] ), ( "./import/jane/2018-include.journal", ["./import/jane/bogartbank/2018-include.journal"] ), ( "./import/jane/2019-include.journal", ["./import/jane/bogartbank/2019-include.journal"] ) ] assertEqual "groupIncludeFiles Jane 3" expectedGroup3 group3 let (group4, allYears4) = groupIncludeFiles (Map.keys group3) let expectedAllYears4 = [ ( "./import/all-years.journal", [ "./import/2017-include.journal", "./import/2018-include.journal", "./import/2019-include.journal" ] ) ] assertEqual "groupIncludeFiles Jane AllYears 4" expectedAllYears4 allYears4 let expectedGroup4 = [ ( "./import/2017-include.journal", ["./import/jane/2017-include.journal"] ), ( "./import/2018-include.journal", ["./import/jane/2018-include.journal"] ), ( "./import/2019-include.journal", ["./import/jane/2019-include.journal"] ) ] assertEqual "groupIncludeFiles Jane 4" expectedGroup4 group4 let (group5, allYears5) = groupIncludeFiles (Map.keys group4) let expectedAllYears5 = [("./all-years.journal", ["./2017-include.journal", "./2018-include.journal", "./2019-include.journal"])] assertEqual "groupIncludeFiles Jane AllYears 5" expectedAllYears5 allYears5 let expectedGroup5 = [ ( "./2017-include.journal", ["./import/2017-include.journal"] ), ( "./2018-include.journal", ["./import/2018-include.journal"] ), ( "./2019-include.journal", ["./import/2019-include.journal"] ) ] assertEqual "groupIncludeFiles Jane 5" expectedGroup5 group5 ) testGroupIncludeFiles :: Test testGroupIncludeFiles = TestCase ( do let (group1, allYears1) = groupIncludeFiles journalFiles let expectedAllYears1 = [ ( "./import/jane/bogartbank/checking/all-years.journal", [ "./import/jane/bogartbank/checking/2018-include.journal", "./import/jane/bogartbank/checking/2019-include.journal" ] ), ( "./import/jane/bogartbank/savings/all-years.journal", [ "./import/jane/bogartbank/savings/2017-include.journal", "./import/jane/bogartbank/savings/2018-include.journal" ] ), ( "./import/jane/otherbank/creditcard/all-years.journal", [ "./import/jane/otherbank/creditcard/2017-include.journal", "./import/jane/otherbank/creditcard/2018-include.journal" ] ), ( "./import/jane/otherbank/investments/all-years.journal", [ "./import/jane/otherbank/investments/2018-include.journal", "./import/jane/otherbank/investments/2019-include.journal" ] ), ( "./import/john/bogartbank/checking/all-years.journal", [ "./import/john/bogartbank/checking/2018-include.journal", "./import/john/bogartbank/checking/2019-include.journal" ] ), ( "./import/john/bogartbank/savings/all-years.journal", [ "./import/john/bogartbank/savings/2017-include.journal", "./import/john/bogartbank/savings/2018-include.journal" ] ), ( "./import/john/otherbank/creditcard/all-years.journal", [ "./import/john/otherbank/creditcard/2017-include.journal", "./import/john/otherbank/creditcard/2018-include.journal" ] ), ( "./import/john/otherbank/investments/all-years.journal", [ "./import/john/otherbank/investments/2018-include.journal", "./import/john/otherbank/investments/2019-include.journal" ] ) ] assertEqual "groupIncludeFiles Jane AllYears 1" expectedAllYears1 allYears1 assertEqual "groupIncludeFiles 1" groupedIncludeFiles group1 let (group2, allYears2) = groupIncludeFiles (Map.keys group1) let expectedAllYears2 = [ ( "./import/jane/bogartbank/all-years.journal", [ "./import/jane/bogartbank/2017-include.journal", "./import/jane/bogartbank/2018-include.journal", "./import/jane/bogartbank/2019-include.journal" ] ), ( "./import/jane/otherbank/all-years.journal", [ "./import/jane/otherbank/2017-include.journal", "./import/jane/otherbank/2018-include.journal", "./import/jane/otherbank/2019-include.journal" ] ), ( "./import/john/bogartbank/all-years.journal", [ "./import/john/bogartbank/2017-include.journal", "./import/john/bogartbank/2018-include.journal", "./import/john/bogartbank/2019-include.journal" ] ), ( "./import/john/otherbank/all-years.journal", [ "./import/john/otherbank/2017-include.journal", "./import/john/otherbank/2018-include.journal", "./import/john/otherbank/2019-include.journal" ] ) ] assertEqual "groupIncludeFiles Jane AllYears 2" expectedAllYears2 allYears2 let expectedGroup2 = [ ( "./import/jane/bogartbank/2017-include.journal", ["./import/jane/bogartbank/savings/2017-include.journal"] ), ( "./import/jane/bogartbank/2018-include.journal", [ "./import/jane/bogartbank/checking/2018-include.journal", "./import/jane/bogartbank/savings/2018-include.journal" ] ), ( "./import/jane/bogartbank/2019-include.journal", ["./import/jane/bogartbank/checking/2019-include.journal"] ), ( "./import/jane/otherbank/2017-include.journal", ["./import/jane/otherbank/creditcard/2017-include.journal"] ), ( "./import/jane/otherbank/2018-include.journal", [ "./import/jane/otherbank/creditcard/2018-include.journal", "./import/jane/otherbank/investments/2018-include.journal" ] ), ( "./import/jane/otherbank/2019-include.journal", ["./import/jane/otherbank/investments/2019-include.journal"] ), ( "./import/john/bogartbank/2017-include.journal", ["./import/john/bogartbank/savings/2017-include.journal"] ), ( "./import/john/bogartbank/2018-include.journal", [ "./import/john/bogartbank/checking/2018-include.journal", "./import/john/bogartbank/savings/2018-include.journal" ] ), ( "./import/john/bogartbank/2019-include.journal", ["./import/john/bogartbank/checking/2019-include.journal"] ), ( "./import/john/otherbank/2017-include.journal", ["./import/john/otherbank/creditcard/2017-include.journal"] ), ( "./import/john/otherbank/2018-include.journal", [ "./import/john/otherbank/creditcard/2018-include.journal", "./import/john/otherbank/investments/2018-include.journal" ] ), ( "./import/john/otherbank/2019-include.journal", ["./import/john/otherbank/investments/2019-include.journal"] ) ] assertEqual "groupIncludeFiles 2 - diff 1" [] (expectedGroup2 Map.\\ group2) assertEqual "groupIncludeFiles 2 - diff 2" [] (group2 Map.\\ expectedGroup2) assertEqual "groupIncludeFiles 2" expectedGroup2 group2 let (group3, allYears3) = groupIncludeFiles (Map.keys group2) let expectedAllYears3 = [ ( "./import/jane/all-years.journal", [ "./import/jane/2017-include.journal", "./import/jane/2018-include.journal", "./import/jane/2019-include.journal" ] ), ( "./import/john/all-years.journal", [ "./import/john/2017-include.journal", "./import/john/2018-include.journal", "./import/john/2019-include.journal" ] ) ] assertEqual "groupIncludeFiles Jane AllYears 3" expectedAllYears3 allYears3 let expectedGroup3 = [ ( "./import/jane/2017-include.journal", [ "./import/jane/bogartbank/2017-include.journal", "./import/jane/otherbank/2017-include.journal" ] ), ( "./import/jane/2018-include.journal", [ "./import/jane/bogartbank/2018-include.journal", "./import/jane/otherbank/2018-include.journal" ] ), ( "./import/jane/2019-include.journal", [ "./import/jane/bogartbank/2019-include.journal", "./import/jane/otherbank/2019-include.journal" ] ), ( "./import/john/2017-include.journal", [ "./import/john/bogartbank/2017-include.journal", "./import/john/otherbank/2017-include.journal" ] ), ( "./import/john/2018-include.journal", [ "./import/john/bogartbank/2018-include.journal", "./import/john/otherbank/2018-include.journal" ] ), ( "./import/john/2019-include.journal", [ "./import/john/bogartbank/2019-include.journal", "./import/john/otherbank/2019-include.journal" ] ) ] assertEqual "groupIncludeFiles 3 - diff 1" [] (expectedGroup3 Map.\\ group3) assertEqual "groupIncludeFiles 3 - diff 2" [] (group3 Map.\\ expectedGroup3) assertEqual "groupIncludeFiles 3" expectedGroup3 group3 let (group4, allYears4) = groupIncludeFiles (Map.keys group3) let expectedAllYears4 = [ ( "./import/all-years.journal", [ "./import/2017-include.journal", "./import/2018-include.journal", "./import/2019-include.journal" ] ) ] assertEqual "groupIncludeFiles Jane AllYears 4" expectedAllYears4 allYears4 let expectedGroup4 = [ ( "./import/2017-include.journal", [ "./import/jane/2017-include.journal", "./import/john/2017-include.journal" ] ), ( "./import/2018-include.journal", [ "./import/jane/2018-include.journal", "./import/john/2018-include.journal" ] ), ( "./import/2019-include.journal", [ "./import/jane/2019-include.journal", "./import/john/2019-include.journal" ] ) ] assertEqual "groupIncludeFiles 4 - diff 1" [] (expectedGroup4 Map.\\ group4) assertEqual "groupIncludeFiles 4 - diff 2" [] (group4 Map.\\ expectedGroup4) assertEqual "groupIncludeFiles 4" expectedGroup4 group4 let (group5, allYears5) = groupIncludeFiles (Map.keys group4) let expectedAllYears5 = [("./all-years.journal", ["./2017-include.journal", "./2018-include.journal", "./2019-include.journal"])] assertEqual "groupIncludeFiles Jane AllYears 5" expectedAllYears5 allYears5 let expectedGroup5 = [ ( "./2017-include.journal", ["./import/2017-include.journal"] ), ( "./2018-include.journal", ["./import/2018-include.journal"] ), ( "./2019-include.journal", ["./import/2019-include.journal"] ) ] assertEqual "groupIncludeFiles 5 - diff 1" [] (expectedGroup5 Map.\\ group5) assertEqual "groupIncludeFiles 5 - diff 2" [] (group5 Map.\\ expectedGroup5) assertEqual "groupIncludeFiles 5" expectedGroup5 group5 ) testIncludeYears :: Test testIncludeYears = TestCase ( do let txterr = "Some text without years" let expectederr = ["Unable to extract years from the following text:", txterr, "Errors:"] let actualerr = case lefts [includeYears' txterr] of (errTxt : _) -> (init . T.lines) errTxt [] -> [] assertEqual "Get a list of years from an include file - error case" expectederr actualerr let txt1 = "### Generated by hledger-flow - DO NOT EDIT ###\n\n" <> "include import/2014-include.journal\n" <> "include import/2015-include.journal\n" <> "include import/2016-include.journal\n" <> "include import/2017-include.journal\n" <> "include import/2018-include.journal\n" <> "include import/2019-include.journal" let expected1 = Right [2014 .. 2019] let actual1 = includeYears' txt1 assertEqual "Get a list of years from an include file - success case 1" expected1 actual1 let txt2 = "include 2019-include.journal" let expected2 = Right [2019] let actual2 = includeYears' txt2 assertEqual "Get a list of years from an include file - success case 2" expected2 actual2 ) testToIncludeLine :: Test testToIncludeLine = TestCase ( do let expected = "include file1.journal" let relativeWithTrailingSlash = toIncludeLine "./base/dir/" "./base/dir/file1.journal" assertEqual "Include line - relative base dir with trailing slash" expected relativeWithTrailingSlash let relativeNoTrailingSlash = toIncludeLine "./base/dir" "./base/dir/file1.journal" assertEqual "Include line - relative base dir without a trailing slash" expected relativeNoTrailingSlash let absoluteWithTrailingSlash = toIncludeLine "/base/dir/" "/base/dir/file1.journal" assertEqual "Include line - absolute base dir with trailing slash" expected absoluteWithTrailingSlash let absoluteNoTrailingSlash = toIncludeLine "/base/dir" "/base/dir/file1.journal" assertEqual "Include line - absolute base dir without a trailing slash" expected absoluteNoTrailingSlash ) testToIncludeFiles :: Test testToIncludeFiles = TestCase ( do let expected = [ ( "./import/john/bogartbank/checking/2018-include.journal", "### Generated by hledger-flow - DO NOT EDIT ###\n\n" <> "include import/john/bogartbank/checking/3-journal/2018/2018-10-30.journal\n" <> "include import/john/bogartbank/checking/3-journal/2018/2018-11-30.journal\n" <> "include import/john/bogartbank/checking/3-journal/2018/2018-12-30.journal\n" ), ( "./import/john/bogartbank/checking/2019-include.journal", "### Generated by hledger-flow - DO NOT EDIT ###\n\n" <> "include import/john/bogartbank/checking/3-journal/2019/2019-01-30.journal\n" <> "include import/john/bogartbank/checking/3-journal/2019/2019-02-30.journal\n" ), ( "./import/john/bogartbank/savings/2017-include.journal", "### Generated by hledger-flow - DO NOT EDIT ###\n\n" <> "include import/john/bogartbank/savings/3-journal/2017/2017-11-30.journal\n" <> "include import/john/bogartbank/savings/3-journal/2017/2017-12-30.journal\n" ), ( "./import/john/bogartbank/savings/2018-include.journal", "### Generated by hledger-flow - DO NOT EDIT ###\n\n" <> "include import/john/bogartbank/savings/3-journal/2018/2018-01-30.journal\n" <> "include import/john/bogartbank/savings/3-journal/2018/2018-02-30.journal\n" ) ] ch <- newTChanIO txt <- toIncludeFiles (defaultOpts [absdir|/|]) ch groupedJohnBogart assertEqual "Convert a grouped map of paths, to a map with text contents for each file" expected txt ) testExtractImportDirsSuccess :: Test testExtractImportDirsSuccess = TestCase ( do let file = "import/john/mybank/checking/1-in/2019/2019-01-01.csv" case extractImportDirs file of Left err -> assertFailure (T.unpack err) Right dirs -> do let expectedYear = Turtle.directory file let expectedState = Turtle.parent expectedYear let expectedAccount = Turtle.parent expectedState let expectedBank = Turtle.parent expectedAccount let expectedOwner = Turtle.parent expectedBank let expectedImport = Turtle.parent expectedOwner assertEqual "importDir" expectedImport (importDir dirs) assertEqual "ownerDir" expectedOwner (ownerDir dirs) assertEqual "bankDir" expectedBank (bankDir dirs) assertEqual "accountDir" expectedAccount (accountDir dirs) assertEqual "stateDir" expectedState (stateDir dirs) assertEqual "yearDir" expectedYear (yearDir dirs) ) testExtractImportDirsFailure :: Test testExtractImportDirsFailure = TestCase ( do let badFile = "import/john/mybank/checking/2019-01-01.csv" case extractImportDirs badFile of Left err -> assertBool "Error should explain expected structure" ("expects to find input files in this structure" `T.isInfixOf` err) Right _ -> assertFailure "Expected failure for malformed import path" ) testGroupIncludeFilesFiltersNonJournal :: Test testGroupIncludeFilesFiltersNonJournal = TestCase ( do let journal = "import/john/mybank/checking/3-journal/2019/2019-01-01.journal" let nonJournal = "import/john/mybank/checking/3-journal/2019/2019-01-01.csv" let (grouped, _) = groupIncludeFiles [journal, nonJournal] assertEqual "Only journal files should be grouped" 1 (Map.size grouped) let files = concat (Map.elems grouped) assertEqual "Non-journal files should be ignored" [journal] files ) tests :: Test tests = TestList [ testYearsIncludeMap, testYearsIncludeGrouping, testGroupIncludeFilesTinySet, testGroupIncludeFilesSmallSet, testGroupIncludeFiles, testIncludeYears, testToIncludeLine, testToIncludeFiles, testExtractImportDirsSuccess, testExtractImportDirsFailure, testGroupIncludeFilesFiltersNonJournal ]