A less bad unit testing setup, makefile cleaned up, includes format, lint, clean, etc.
This commit is contained in:
parent
31d54641bc
commit
8d018fc168
44
Makefile
44
Makefile
@ -1,34 +1,32 @@
|
|||||||
code := $(wildcard src/*)
|
.PHONY: help run test clean format
|
||||||
test_directories := $(wildcard tests/*)
|
|
||||||
test_targets := $(addsuffix /pass,$(test_directories))
|
|
||||||
existing_passes := $(wildcard tests/*/pass)
|
|
||||||
out_files := $(wildcard tests/*/*.out)
|
|
||||||
out_files += $(wildcard tests/*/out.*)
|
|
||||||
|
|
||||||
.PHONY: help build run test clean
|
|
||||||
|
|
||||||
help: # Show help for each of the commented Makefile recipes.
|
help: # Show help for each of the commented Makefile recipes.
|
||||||
@grep -E '^[a-zA-Z0-9 -]+:.*#' Makefile | sort | while read -r l; \
|
@grep -E '^[a-zA-Z0-9 -]+:.*#' Makefile | sort | while read -r l; \
|
||||||
do printf "\033[1;32m$$(echo $$l | cut -f 1 -d':')\033[00m:$$(echo $$l | cut -f 2- -d'#')\n"; done
|
do printf "\033[1;32m$$(echo $$l | cut -f 1 -d':')\033[00m:$$(echo $$l | cut -f 2- -d'#')\n"; done
|
||||||
|
|
||||||
tests/%/pass: $(code)
|
run: target/Main.out # Runs your compiled main code.
|
||||||
cd $(patsubst %/pass,%/,$@) && $(MAKE)
|
./target/Main.out
|
||||||
|
|
||||||
build: $(code) # Builds your code alone (does not build not any unit tests).
|
target/Main.out: src/*
|
||||||
cd src && $(MAKE)
|
ghc -g -fprof-auto -prof -Wall src/*.hs -o target/Main.out
|
||||||
|
@rm -f src/*.o src/*.hi
|
||||||
|
|
||||||
run: build # Runs your compiled main code (does not pass any args or std-io).
|
test: tests/*.hs # Runs unit tests.
|
||||||
./target/main.out
|
runghc -i./src/ tests/Main.hs
|
||||||
|
|
||||||
test: $(test_targets) # Runs test code, generating score logfiles. To run past failing tests, use: `make test --keep-going`
|
format: src/* # Formats code using ormolu.
|
||||||
@#$(MAKE) grade
|
ormolu --mode inplace src/*.hs tests/*.hs
|
||||||
|
|
||||||
|
hlint: src/*.hs # HLint for lint suggestions.
|
||||||
|
hlint src/*.hs
|
||||||
|
|
||||||
|
stan: src/*.hs # Stan for more optimization suggestions.
|
||||||
|
ghc -fwrite-ide-info src/*.hs -o target/temp.out
|
||||||
|
stan --hiedir src/
|
||||||
|
rm -f target/temp.out src/*.hi src/*.o src/*.hie
|
||||||
|
|
||||||
clean: # Cleans up all the generated logfiles and outfiles.
|
clean: # Cleans up all the generated logfiles and outfiles.
|
||||||
@rm -f $(test_targets)
|
@rm -rf *.out *.o *.hi
|
||||||
@rm -f $(out_files)
|
|
||||||
@rm -rf .mypy_cache __pycache__ *.out *.o *.hi .gdb_history
|
|
||||||
@rm -rf build/*
|
|
||||||
@rm -rf target/*
|
@rm -rf target/*
|
||||||
@rm -rf .admin_files/.mypy_cache .admin_files/__pycache__ .admin_files/*.hi .admin_files/*.o
|
@rm -rf */*.out */*.o */*.hi
|
||||||
@rm -rf */.mypy_cache */__pycache__ */*.out */*.o */*.hi
|
@rm -rf */*/*.out */*/*.o */*/*.hi
|
||||||
@rm -rf */*/.mypy_cache */*/__pycache__ */*/*.out */*/*.o */*/*.hi */*/.gdb_history
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
import Control.Exception (assert)
|
import Control.Exception (assert)
|
||||||
import GP
|
import GP
|
||||||
import Push
|
import Push
|
@ -1,3 +0,0 @@
|
|||||||
../target/main.out: *.hs
|
|
||||||
ghc -g -fprof-auto -prof -Wall *.hs -o ../target/main.out
|
|
||||||
@rm -f *.o *.hi
|
|
74
src/Tests.hs
74
src/Tests.hs
@ -1,74 +0,0 @@
|
|||||||
module Tests where
|
|
||||||
|
|
||||||
import qualified Data.Map as Map
|
|
||||||
import Push
|
|
||||||
|
|
||||||
exampleState =
|
|
||||||
State
|
|
||||||
{ exec = [IntGene 5, StateFunc instructionParameterLoad, StateFunc instructionIntAdd],
|
|
||||||
int = [2, 6, 3],
|
|
||||||
float = [1.2, 1.7],
|
|
||||||
bool = [True, False],
|
|
||||||
string = ["Hello", "Push"],
|
|
||||||
parameter = [IntGene 1, StringGene "Hi", BoolGene True, FloatGene 1.3],
|
|
||||||
input = Map.fromList [("in0" , IntGene 1)]
|
|
||||||
}
|
|
||||||
|
|
||||||
-- TODO: Tests for added basic int instructions
|
|
||||||
|
|
||||||
testResult1 = [8, 3] == int (instructionIntAdd exampleState)
|
|
||||||
|
|
||||||
testResult2 = [4, 3] == int (instructionIntSub exampleState)
|
|
||||||
|
|
||||||
testResult3 = [12, 3] == int (instructionIntMul exampleState)
|
|
||||||
|
|
||||||
testResult4 = [3, 3] == int (instructionIntDiv exampleState)
|
|
||||||
|
|
||||||
testResult5 = [6, 2, 6, 3] == int (interpretExec exampleState)
|
|
||||||
|
|
||||||
loadedState = loadProgram [IntGene 6, IntGene 6, StateFunc instructionIntAdd] emptyState
|
|
||||||
testResult6 = [12] == int (interpretExec loadedState)
|
|
||||||
|
|
||||||
loadedState2 = loadProgram [BoolGene True, StateFunc instructionExecIf, Block [IntGene 5, IntGene 6], Block [IntGene 7, IntGene 8]] emptyState
|
|
||||||
testResult7 = [6, 5] == int (interpretExec loadedState2)
|
|
||||||
|
|
||||||
loadedState3 = loadProgram [BoolGene False, StateFunc instructionExecIf, Block [IntGene 5, IntGene 6], Block [IntGene 7, IntGene 8]] emptyState
|
|
||||||
testResult8 = [8, 7] == int (interpretExec loadedState3)
|
|
||||||
|
|
||||||
-- Tests input map
|
|
||||||
loadedState4 = loadProgram [BoolGene False, PlaceInput "in0", StateFunc instructionIntAdd] exampleState
|
|
||||||
testResult9 = [3, 6, 3] == int (interpretExec loadedState4)
|
|
||||||
|
|
||||||
-- Tests execDup
|
|
||||||
loadedState5 = interpretExec $ loadProgram [StateFunc instructionExecDup, IntGene 2] emptyState
|
|
||||||
testResult10 = int loadedState5 !! 0 == 2 && int loadedState5 !! 1 == 2
|
|
||||||
|
|
||||||
-- Tests execDoRange
|
|
||||||
loadedState6 = loadProgram [IntGene 2, Block [IntGene 4, IntGene 1, StateFunc instructionExecDoRange], StateFunc instructionIntAdd] emptyState
|
|
||||||
testResult11 = [12] == int (interpretExec loadedState6)
|
|
||||||
|
|
||||||
-- Tests execDoCount
|
|
||||||
loadedState7 = loadProgram [IntGene 2, Block [IntGene 4, StateFunc instructionExecDoCount], StateFunc instructionIntAdd] emptyState
|
|
||||||
testResult12 = [8] == int (interpretExec loadedState7)
|
|
||||||
|
|
||||||
-- Tests execDoTimes
|
|
||||||
loadedState8 = loadProgram [IntGene 2, Block [IntGene 4, StateFunc instructionExecDoTimes], IntGene 69] emptyState
|
|
||||||
testResult13 = [69, 69, 69, 69, 2] == int (interpretExec loadedState8)
|
|
||||||
|
|
||||||
-- Tests execWhile
|
|
||||||
loadedState9 = loadProgram [BoolGene False, BoolGene True, BoolGene True, StateFunc instructionExecWhile, IntGene 70] emptyState
|
|
||||||
testResult14 = [70, 70] == int (interpretExec loadedState9)
|
|
||||||
|
|
||||||
-- Tests execDoWhile
|
|
||||||
loadedState10 = loadProgram [BoolGene False, BoolGene True, BoolGene True, StateFunc instructionExecDoWhile, IntGene 70] emptyState
|
|
||||||
testResult15 = [70, 70, 70] == int (interpretExec loadedState10)
|
|
||||||
|
|
||||||
-- Tests execWhen
|
|
||||||
loadedState11 = loadProgram [BoolGene False, StateFunc instructionExecWhen, IntGene 71] emptyState
|
|
||||||
testResult16 = emptyState == interpretExec loadedState11
|
|
||||||
|
|
||||||
-- Also tests execWhen
|
|
||||||
loadedState12 = loadProgram [BoolGene True, StateFunc instructionExecWhen, IntGene 71] emptyState
|
|
||||||
testResult17 = [71] == int (interpretExec loadedState12)
|
|
||||||
|
|
||||||
allTests = and [testResult1, testResult2, testResult3, testResult4, testResult5, testResult6, testResult7, testResult8, testResult9]
|
|
75
tests/Main.hs
Normal file
75
tests/Main.hs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import Control.Exception (assert)
|
||||||
|
import qualified Data.Map as Map
|
||||||
|
import Push
|
||||||
|
import Test.Hspec
|
||||||
|
import Test.Hspec.QuickCheck
|
||||||
|
import Test.QuickCheck
|
||||||
|
|
||||||
|
exampleState =
|
||||||
|
State
|
||||||
|
{ exec = [IntGene 5, StateFunc instructionParameterLoad, StateFunc instructionIntAdd],
|
||||||
|
int = [2, 6, 3],
|
||||||
|
float = [1.2, 1.7],
|
||||||
|
bool = [True, False],
|
||||||
|
string = ["Hello", "Push"],
|
||||||
|
parameter = [IntGene 1, StringGene "Hi", BoolGene True, FloatGene 1.3],
|
||||||
|
input = Map.fromList [("in0", IntGene 1)]
|
||||||
|
}
|
||||||
|
|
||||||
|
prop_test1 :: [Int] -> Bool
|
||||||
|
prop_test1 nums = nums == reverse (reverse nums)
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
quickCheck prop_test1
|
||||||
|
assert ([8, 3] == int (instructionIntAdd exampleState)) putStrLn "Add test pass"
|
||||||
|
assert ([4, 3] == int (instructionIntSub exampleState)) putStrLn "Sub test pass"
|
||||||
|
assert ([12, 3] == int (instructionIntMul exampleState)) putStrLn "Mult test pass"
|
||||||
|
assert ([3, 3] == int (instructionIntDiv exampleState)) putStrLn "Div test pass"
|
||||||
|
assert ([6, 2, 6, 3] == int (interpretExec exampleState)) putStrLn "Interpret test pass"
|
||||||
|
|
||||||
|
let loadedState = loadProgram [IntGene 6, IntGene 6, StateFunc instructionIntAdd] emptyState
|
||||||
|
assert ([12] == int (interpretExec loadedState)) putStrLn "Interpret test 2 pass"
|
||||||
|
|
||||||
|
let loadedState2 = loadProgram [BoolGene True, StateFunc instructionExecIf, Block [IntGene 5, IntGene 6], Block [IntGene 7, IntGene 8]] emptyState
|
||||||
|
assert ([6, 5] == int (interpretExec loadedState2)) putStrLn "execIf"
|
||||||
|
|
||||||
|
let loadedState3 = loadProgram [BoolGene False, StateFunc instructionExecIf, Block [IntGene 5, IntGene 6], Block [IntGene 7, IntGene 8]] emptyState
|
||||||
|
assert ([8, 7] == int (interpretExec loadedState3)) putStrLn "execIf"
|
||||||
|
|
||||||
|
let loadedState4 = loadProgram [BoolGene False, PlaceInput "in0", StateFunc instructionIntAdd] exampleState
|
||||||
|
assert ([3, 6, 3] == int (interpretExec loadedState4)) putStrLn "input map"
|
||||||
|
|
||||||
|
let loadedState5 = interpretExec $ loadProgram [StateFunc instructionExecDup, IntGene 2] emptyState
|
||||||
|
assert (int loadedState5 !! 0 == 2 && int loadedState5 !! 1 == 2) putStrLn "execDup"
|
||||||
|
|
||||||
|
let loadedState6 = loadProgram [IntGene 2, Block [IntGene 4, IntGene 1, StateFunc instructionExecDoRange], StateFunc instructionIntAdd] emptyState
|
||||||
|
assert ([12] == int (interpretExec loadedState6)) putStrLn "execDoRange"
|
||||||
|
|
||||||
|
let loadedState7 = loadProgram [IntGene 2, Block [IntGene 4, StateFunc instructionExecDoCount], StateFunc instructionIntAdd] emptyState
|
||||||
|
assert ([8] == int (interpretExec loadedState7)) putStrLn "execDoCount"
|
||||||
|
|
||||||
|
let loadedState8 = loadProgram [IntGene 2, Block [IntGene 4, StateFunc instructionExecDoTimes], IntGene 69] emptyState
|
||||||
|
assert ([69, 69, 69, 69, 2] == int (interpretExec loadedState8)) putStrLn "execDoTimes"
|
||||||
|
|
||||||
|
let loadedState9 = loadProgram [BoolGene False, BoolGene True, BoolGene True, StateFunc instructionExecWhile, IntGene 70] emptyState
|
||||||
|
assert ([70, 70] == int (interpretExec loadedState9)) putStrLn "execWhile"
|
||||||
|
|
||||||
|
let loadedState10 = loadProgram [BoolGene False, BoolGene True, BoolGene True, StateFunc instructionExecDoWhile, IntGene 70] emptyState
|
||||||
|
assert ([70, 70, 70] == int (interpretExec loadedState10)) putStrLn "execDoWhile"
|
||||||
|
|
||||||
|
let loadedState11 = loadProgram [BoolGene False, StateFunc instructionExecWhen, IntGene 71] emptyState
|
||||||
|
assert (emptyState == interpretExec loadedState11) putStrLn "execWhen"
|
||||||
|
|
||||||
|
let loadedState12 = loadProgram [BoolGene True, StateFunc instructionExecWhen, IntGene 71] emptyState
|
||||||
|
assert ([71] == int (interpretExec loadedState12)) putStrLn "execWhen"
|
||||||
|
|
||||||
|
hspec $ do
|
||||||
|
describe "Prelude.read" $ do
|
||||||
|
it "can parse integers" $ do
|
||||||
|
read "10" `shouldBe` (10 :: Int)
|
||||||
|
|
||||||
|
describe "read" $ do
|
||||||
|
it "is inverse to show" $
|
||||||
|
property $
|
||||||
|
\x -> (read . show) x `shouldBe` (x :: Int)
|
@ -1,7 +0,0 @@
|
|||||||
-- https://stackoverflow.com/questions/8867350/how-to-set-a-programs-command-line-arguments-for-ghci
|
|
||||||
-- :set args is a GHCI thing:
|
|
||||||
-- https://downloads.haskell.org/ghc/latest/docs/users_guide/ghci.html#ghci-commands
|
|
||||||
:set stop :list
|
|
||||||
:load ../../src/main.hs ../../src/BinaryConversions.hs
|
|
||||||
:set args "argfile.in" "argfile.out"
|
|
||||||
:step main
|
|
@ -1,10 +0,0 @@
|
|||||||
pass: ../../src/*
|
|
||||||
cd ../../src/ && $(MAKE)
|
|
||||||
./../../target/main.out argfile.in argfile.out
|
|
||||||
delta argfile.goal argfile.out && echo 100 >pass \
|
|
||||||
|| ([[ "$$IS_PIPELINE" ]] && exit 1 \
|
|
||||||
|| (echo "Press enter to debug:" && read && $(MAKE) debug && exit 1))
|
|
||||||
|
|
||||||
.PHONY: debug
|
|
||||||
debug:
|
|
||||||
ghci
|
|
@ -1 +0,0 @@
|
|||||||
1010
|
|
@ -1 +0,0 @@
|
|||||||
10
|
|
@ -1,7 +0,0 @@
|
|||||||
-- https://stackoverflow.com/questions/8867350/how-to-set-a-programs-command-line-arguments-for-ghci
|
|
||||||
-- :set args is a GHCI thing:
|
|
||||||
-- https://downloads.haskell.org/ghc/latest/docs/users_guide/ghci.html#ghci-commands
|
|
||||||
:set stop :list
|
|
||||||
:load ../../src/main.hs ../../src/BinaryConversions.hs
|
|
||||||
:set args "argfile.in" "argfile.out"
|
|
||||||
:step main
|
|
@ -1,10 +0,0 @@
|
|||||||
pass: ../../src/*
|
|
||||||
cd ../../src/ && $(MAKE)
|
|
||||||
./../../target/main.out argfile.in argfile.out
|
|
||||||
python3 ../../.admin_files/fuzzydiffer.py argfile.goal argfile.out >pass \
|
|
||||||
|| ([[ "$$IS_PIPELINE" ]] && exit 1 \
|
|
||||||
|| (echo -e "$$(delta argfile.goal argfile.out)\nPress enter to debug:" && read && $(MAKE) debug && exit 1))
|
|
||||||
|
|
||||||
.PHONY: debug
|
|
||||||
debug:
|
|
||||||
ghci
|
|
@ -1 +0,0 @@
|
|||||||
1010
|
|
@ -1 +0,0 @@
|
|||||||
10
|
|
@ -1,3 +0,0 @@
|
|||||||
pass: ../../src/*.hs
|
|
||||||
echo $$PATH
|
|
||||||
doctest --verbose $^ && echo 100 >pass
|
|
@ -1,2 +0,0 @@
|
|||||||
pass: ../../src/*.hs
|
|
||||||
ormolu --mode check $^ && echo 100 >pass
|
|
@ -1,2 +0,0 @@
|
|||||||
pass: ../../src/*.hs
|
|
||||||
hlint $^ && echo 100 >pass
|
|
@ -1,13 +0,0 @@
|
|||||||
pass: ../../src/*.hs
|
|
||||||
ghc -fwrite-ide-info $^ -o main.out
|
|
||||||
stan --hiedir ../../src/ | grep "Total found observations ┃ 0" && echo 100 >pass \
|
|
||||||
|| ([[ "$$IS_PIPELINE" ]] && exit 1 \
|
|
||||||
|| (echo -e "\nPress enter to debug:" && read && $(MAKE) debug && exit 1))
|
|
||||||
@rm -f ../../src/*.hie ../../src/*.hi ../../src/*.o main.out
|
|
||||||
|
|
||||||
.PHONY: debug
|
|
||||||
debug:
|
|
||||||
ghc -fwrite-ide-info ../../src/*.hs -o main.out
|
|
||||||
stan --hiedir ../../src/
|
|
||||||
@rm -f ../../src/*.hie ../../src/*.hi ../../src/*.o main.out
|
|
||||||
@echo "To get points, fix the above 'observations'."
|
|
@ -1,3 +0,0 @@
|
|||||||
pass: ../../src/*.hs
|
|
||||||
ghc -Wall -Werror $^ -o main.out && echo 100 >pass || (rm main.out && exit 1)
|
|
||||||
@rm main.out
|
|
@ -1,3 +0,0 @@
|
|||||||
:set stop :list
|
|
||||||
:load ../../src/main.hs ../../src/BinaryConversions.hs
|
|
||||||
:step main
|
|
@ -1,10 +0,0 @@
|
|||||||
pass: ../../src/*
|
|
||||||
cd ../../src/ && $(MAKE)
|
|
||||||
./../../target/main.out <std.in >std.out
|
|
||||||
delta std.goal std.out && echo 100 >pass \
|
|
||||||
|| ([[ "$$IS_PIPELINE" ]] && exit 1 \
|
|
||||||
|| (echo "Press enter to debug (type std.in in yourself):" && read && $(MAKE) debug && exit 1))
|
|
||||||
|
|
||||||
.PHONY: debug
|
|
||||||
debug:
|
|
||||||
ghci
|
|
@ -1 +0,0 @@
|
|||||||
1010
|
|
@ -1 +0,0 @@
|
|||||||
10
|
|
@ -1,3 +0,0 @@
|
|||||||
:set stop :list
|
|
||||||
:load ../../src/main.hs ../../src/BinaryConversions.hs
|
|
||||||
:step main
|
|
@ -1,10 +0,0 @@
|
|||||||
pass: ../../src/*
|
|
||||||
cd ../../src/ && $(MAKE)
|
|
||||||
./../../target/main.out <std.in >std.out
|
|
||||||
python3 ../../.admin_files/fuzzydiffer.py std.goal std.out >pass \
|
|
||||||
|| ([[ "$$IS_PIPELINE" ]] && exit 1 \
|
|
||||||
|| (echo -e "$$(delta std.goal std.out)\nPress enter to debug (type std.in yourself):" && read && $(MAKE) debug && exit 1))
|
|
||||||
|
|
||||||
.PHONY: debug
|
|
||||||
debug:
|
|
||||||
ghci
|
|
@ -1 +0,0 @@
|
|||||||
1010
|
|
@ -1 +0,0 @@
|
|||||||
10
|
|
@ -1,3 +0,0 @@
|
|||||||
:set stop :list
|
|
||||||
:load unit.hs ../../src/BinaryConversions.hs
|
|
||||||
:step main
|
|
@ -1,10 +0,0 @@
|
|||||||
pass: ../../src/*
|
|
||||||
ghc -g -fprof-auto -prof -Wall unit.hs ../../src/BinaryConversions.hs -o unit.out
|
|
||||||
@rm -f *.o *.hi
|
|
||||||
./unit.out && echo 100 >pass \
|
|
||||||
|| ([[ "$$IS_PIPELINE" ]] && exit 1 \
|
|
||||||
|| (echo "Press enter to debug:" && read && $(MAKE) debug && exit 1))
|
|
||||||
|
|
||||||
.PHONY: debug
|
|
||||||
debug:
|
|
||||||
ghci
|
|
@ -1,7 +0,0 @@
|
|||||||
import BinaryConversions
|
|
||||||
import Control.Exception (assert)
|
|
||||||
|
|
||||||
main :: IO ()
|
|
||||||
main = do
|
|
||||||
let nums = [1, 2 .. 10]
|
|
||||||
assert (nums == map (binToNat . natToBin) nums) pure ()
|
|
@ -1,3 +0,0 @@
|
|||||||
:set stop :list
|
|
||||||
:load unit.hs ../../src/BinaryConversions.hs
|
|
||||||
:step main
|
|
@ -1,10 +0,0 @@
|
|||||||
pass: ../../src/*
|
|
||||||
ghc -g -fprof-auto -prof -Wall unit.hs ../../src/BinaryConversions.hs -o unit.out
|
|
||||||
@rm -f *.o *.hi
|
|
||||||
./unit.out | grep "OK" && echo 100 >pass \
|
|
||||||
|| ([[ "$$IS_PIPELINE" ]] && exit 1 \
|
|
||||||
|| (echo "Press enter to debug:" && read && $(MAKE) debug && exit 1))
|
|
||||||
|
|
||||||
.PHONY: debug
|
|
||||||
debug:
|
|
||||||
ghci
|
|
@ -1,10 +0,0 @@
|
|||||||
import BinaryConversions
|
|
||||||
import Numeric.Natural (Natural)
|
|
||||||
import Test.QuickCheck
|
|
||||||
import Test.QuickCheck.Instances.Natural ()
|
|
||||||
|
|
||||||
test :: [Natural] -> Bool
|
|
||||||
test nums = nums == map (binToNat . natToBin) nums
|
|
||||||
|
|
||||||
main :: IO ()
|
|
||||||
main = quickCheck test
|
|
Loading…
x
Reference in New Issue
Block a user