-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #433 from smucclaw/le-tests
Le tests
- Loading branch information
Showing
15 changed files
with
843 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
the target language is: prolog. | ||
|
||
the templates are: | ||
*a var* is *a var*. | ||
*a class*'s *a field* is *a value*, | ||
*a class*'s nested *a list of fields* is *a value*, | ||
*a class*'s *a field0*'s *a field1* is *a value*, | ||
*a class*'s *a field0*'s *a field1*'s *a field2* is *a value*, | ||
*a class*'s *a field0*'s *a field1*'s *a field2*'s *a field3* is *a value*, | ||
*a class*'s *a field0*'s *a field1*'s *a field2*'s *a field3*'s *a field4* is *a value*. | ||
|
||
*a number* is a lower bound of *a list*, | ||
*a number* is an upper bound of *a list*, | ||
*a number* is the minimum of *a number* and the maximum of *a number* and *a number*, | ||
the sum of *a list* does not exceed the minimum of *a list*, | ||
*a number* does not exceed the minimum of *a list*. | ||
|
||
% Predefined stdlib for translating natural4 -> LE. | ||
the knowledge base prelude includes: | ||
% Note: LE's parsing of [H | T] is broken atm because it transforms that | ||
% into [H, T] rather than the Prolog term [H | T]. | ||
|
||
% a class's nested [] is a value. | ||
|
||
% a class's nested [a field | a fields] is a value | ||
% if the class's the field is an other class | ||
% and the other class's nested the fields is the value. | ||
|
||
% Nested accessor predicates. | ||
a class's a field0's a field1 is a value | ||
if class's field0 is a class0 | ||
and class0's field1 is value. | ||
|
||
a class's a field0's a field1's a field2 is a value | ||
if class's field0 is a class0 | ||
and class0's field1 is a class1 | ||
and class1's field2 is value. | ||
|
||
a class's a field0's a field1's a field2's a field3 is a value | ||
if class's field0 is a class0 | ||
and class0's field1 is a class1 | ||
and class1's field2 is a class2 | ||
and class2's field3 is value. | ||
|
||
a class's a field0's a field1's a field2's a field3's a field4 is a value | ||
if the class's field0 is a class0 | ||
and class0's field1 is a class1 | ||
and class1's field2 is a class2 | ||
and class2's field3 is a class3 | ||
and class3's field4 is value. | ||
|
||
% Arithmetic predicates. | ||
a number is an upper bound of a list | ||
if for all cases in which | ||
a X is in list | ||
it is the case that | ||
X is [a class, a field] | ||
and class's field is a value | ||
and number >= value | ||
or number >= X. | ||
|
||
a number is a lower bound of a list | ||
if for all cases in which | ||
a X is in list | ||
it is the case that | ||
X is [a class, a field] | ||
and class's field is a value | ||
and number =< value | ||
or number =< X. | ||
|
||
% number = min(x, max(y, z)) | ||
a number is the minimum of a x and the maximum of a y and a z | ||
if a m is the maximum of [y, z] | ||
and number is the minimum of [x, m]. | ||
|
||
a number does not exceed the minimum of a list of numbers | ||
if a min is the minimum of list of numbers | ||
and number =< min. | ||
|
||
the sum of a list does not exceed the minimum of a other list | ||
if a x is the sum of list | ||
and x does not exceed the minimum of other list. | ||
|
||
the knowledge base encoding includes: | ||
a total savings is 100 | ||
if a initial savings is 22.5. | ||
|
||
query q is: | ||
0 < 1. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
the target language is: prolog. | ||
|
||
the templates are: | ||
*a var* is *a var*. | ||
*a class*'s *a field* is *a value*, | ||
*a class*'s nested *a list of fields* is *a value*, | ||
*a class*'s *a field0*'s *a field1* is *a value*, | ||
*a class*'s *a field0*'s *a field1*'s *a field2* is *a value*, | ||
*a class*'s *a field0*'s *a field1*'s *a field2*'s *a field3* is *a value*, | ||
*a class*'s *a field0*'s *a field1*'s *a field2*'s *a field3*'s *a field4* is *a value*. | ||
|
||
*a number* is a lower bound of *a list*, | ||
*a number* is an upper bound of *a list*, | ||
*a number* is the minimum of *a number* and the maximum of *a number* and *a number*, | ||
the sum of *a list* does not exceed the minimum of *a list*, | ||
*a number* does not exceed the minimum of *a list*. | ||
|
||
% Predefined stdlib for translating natural4 -> LE. | ||
the knowledge base prelude includes: | ||
% Note: LE's parsing of [H | T] is broken atm because it transforms that | ||
% into [H, T] rather than the Prolog term [H | T]. | ||
|
||
% a class's nested [] is a value. | ||
|
||
% a class's nested [a field | a fields] is a value | ||
% if the class's the field is an other class | ||
% and the other class's nested the fields is the value. | ||
|
||
% Nested accessor predicates. | ||
a class's a field0's a field1 is a value | ||
if class's field0 is a class0 | ||
and class0's field1 is value. | ||
|
||
a class's a field0's a field1's a field2 is a value | ||
if class's field0 is a class0 | ||
and class0's field1 is a class1 | ||
and class1's field2 is value. | ||
|
||
a class's a field0's a field1's a field2's a field3 is a value | ||
if class's field0 is a class0 | ||
and class0's field1 is a class1 | ||
and class1's field2 is a class2 | ||
and class2's field3 is value. | ||
|
||
a class's a field0's a field1's a field2's a field3's a field4 is a value | ||
if the class's field0 is a class0 | ||
and class0's field1 is a class1 | ||
and class1's field2 is a class2 | ||
and class2's field3 is a class3 | ||
and class3's field4 is value. | ||
|
||
% Arithmetic predicates. | ||
a number is an upper bound of a list | ||
if for all cases in which | ||
a X is in list | ||
it is the case that | ||
X is [a class, a field] | ||
and class's field is a value | ||
and number >= value | ||
or number >= X. | ||
|
||
a number is a lower bound of a list | ||
if for all cases in which | ||
a X is in list | ||
it is the case that | ||
X is [a class, a field] | ||
and class's field is a value | ||
and number =< value | ||
or number =< X. | ||
|
||
% number = min(x, max(y, z)) | ||
a number is the minimum of a x and the maximum of a y and a z | ||
if a m is the maximum of [y, z] | ||
and number is the minimum of [x, m]. | ||
|
||
a number does not exceed the minimum of a list of numbers | ||
if a min is the minimum of list of numbers | ||
and number =< min. | ||
|
||
the sum of a list does not exceed the minimum of a other list | ||
if a x is the sum of list | ||
and x does not exceed the minimum of other list. | ||
|
||
the knowledge base encoding includes: | ||
a total savings is 100 | ||
if a initial savings is 22.5. | ||
|
||
query q is: | ||
0 < 1. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
lib/haskell/natural4/test/LS/XPile/LogicalEnglish/GoldenUtils.hs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
module LS.XPile.LogicalEnglish.GoldenUtils (goldenLE) where | ||
|
||
import LS.XPile.LogicalEnglish.UtilsLEReplDev (leTestcasesDir) | ||
import System.FilePath ((</>), takeBaseName) | ||
import Test.Hspec.Golden (Golden (..)) | ||
|
||
goldenLE :: FilePath -> String -> Golden String | ||
goldenLE testcase actualOutput = | ||
Golden | ||
{ output = actualOutput, | ||
encodePretty = show, | ||
writeToFile = writeFile, | ||
readFromFile = readFile, | ||
goldenFile = leTestcasesDir </> testcaseName </> "expected.le", | ||
actualFile = Just $ leTestcasesDir </> testcaseName </> "actual.le", | ||
failFirstTime = False | ||
} | ||
where | ||
testcaseName = takeBaseName testcase |
72 changes: 72 additions & 0 deletions
72
lib/haskell/natural4/test/LS/XPile/LogicalEnglish/LogicalEnglishSpec.hs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
{-# LANGUAGE BlockArguments #-} | ||
|
||
-- | | ||
-- Module: LogicalEnglishSpec | ||
-- Description: Defines a hspec Spec for testing the Logical English transpiler. | ||
-- | ||
-- This module is responsible for running unit tests for the Logical English | ||
-- transpiler. | ||
-- To define a test case, one can create a new directory in | ||
-- leTestcasesDir, like 'is-num' with the following structure: | ||
-- - {leTestcasesDir} | ||
-- - is-num | ||
-- - is-num.csv | ||
-- - expected.le | ||
-- - config.yml | ||
-- where: | ||
-- - 'is-num.csv' is the name of the input natural4 csv file. | ||
-- - 'expected.le' is a file containing the expected Logical English output. | ||
-- - 'condig.yml' is a YAML configuration file for the unit test. | ||
-- | ||
-- Note that: | ||
-- - 'config.yml' should look something like: | ||
-- description: "If IS is followed by a number, number should become *a number*" | ||
-- enabled: true | ||
-- - ie it should contain a string field called 'description', which gives | ||
-- the description of the test case found in that directory, and | ||
-- 'enabled' is a boolean (ie 'true' or 'false') indicating if the test | ||
-- case is currently enabled. | ||
-- Test cases which are not enabled are skipped automatically by this module. | ||
-- | ||
-- - The file names 'expected.le' and 'config.yml' are hardcoded | ||
-- and so should not be varied | ||
-- - The name of the parent directory and csv file can be changed, but should be | ||
-- kept in sync with each other, ie if the parent directory is 'abc', then | ||
-- the csv file should be called 'abc.csv'. | ||
-- | ||
-- After creating a unit test, one can register it to be run by this module | ||
-- by adding the name of the directory as an entry in | ||
-- '{leTestcasesDir}/testcases.yml'. | ||
-- Only those test cases which are listed in this file will be run. | ||
-- | ||
-- When Logical English test cases are run via 'stack test', a new file called | ||
-- 'actual.le' will appear in the respective directories of each test case | ||
-- that was run. | ||
-- This file represents the actual output of the Logical English transpiler. | ||
module LS.XPile.LogicalEnglish.LogicalEnglishSpec (spec) where | ||
|
||
import Control.Monad (join) | ||
import Data.Foldable (for_) | ||
import Flow ((|>)) | ||
import LS.Utils ((|$>)) | ||
import LS.XPile.LogicalEnglish.Testcase (configFile2spec) | ||
import LS.XPile.LogicalEnglish.SpecUtils (findWithDepth0) | ||
import LS.XPile.LogicalEnglish.UtilsLEReplDev (leTestcasesDir) | ||
import Safe (tailSafe) | ||
import System.FilePath ((</>)) | ||
import System.FilePath.Find (FileType (Directory), fileType, (==?)) | ||
import Test.Hspec (Spec, describe, runIO) | ||
|
||
-- | The 'Spec' used to test the Logical English transpiler. | ||
spec :: Spec | ||
spec = describe "Logical English" do | ||
directories :: [FilePath] <- | ||
leTestcasesDir | ||
|> findWithDepth0 (fileType ==? Directory) | ||
-- The first directory will always be leTestcasesDir itself, which is why | ||
-- we need to take the tail to get rid of it. | ||
|$> tailSafe | ||
|> runIO | ||
for_ directories \directory -> | ||
directory </> "config.yml" | ||
|> configFile2spec |> runIO |> join |
17 changes: 17 additions & 0 deletions
17
lib/haskell/natural4/test/LS/XPile/LogicalEnglish/SpecUtils.hs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
module LS.XPile.LogicalEnglish.SpecUtils | ||
( findWithDepth0, | ||
modifyError | ||
) | ||
where | ||
|
||
import Control.Monad.Except | ||
( runExceptT, MonadError(throwError), ExceptT ) | ||
import System.FilePath.Find (depth, (==?)) | ||
import System.FilePath.Find qualified as FileFind | ||
|
||
findWithDepth0 :: FileFind.FilterPredicate -> FilePath -> IO [FilePath] | ||
findWithDepth0 = FileFind.find (depth ==? 0) | ||
|
||
-- | Backported from mtl-2.3.1 | ||
modifyError :: MonadError e' m => (e -> e') -> ExceptT e m a -> m a | ||
modifyError f m = runExceptT m >>= either (throwError . f) pure |
Oops, something went wrong.