Initial commit, ACM PEARC25 and PEARC26 chosen restaurants work.
Committer: hpcdisrespecter <noreply@git.asperger.pro> modified: .gitignore modified: README.md new file: menus/peoples-organic.sexp new file: menus/townhall-shortnorth.sexp new file: organic-cafe.asd new file: run.lisp new file: src/package.lisp new file: src/planner.lisp new file: test/tests.lisp
This commit is contained in:
150
test/tests.lisp
Normal file
150
test/tests.lisp
Normal file
@@ -0,0 +1,150 @@
|
||||
(defpackage #:organic-cafe/tests
|
||||
(:use #:cl)
|
||||
(:export #:run-tests))
|
||||
|
||||
(in-package #:organic-cafe/tests)
|
||||
|
||||
(defun menu-path (filename)
|
||||
(asdf:system-relative-pathname
|
||||
"organic-cafe"
|
||||
(format nil "menus/~A" filename)))
|
||||
|
||||
(defmacro check (form)
|
||||
`(unless ,form
|
||||
(error "Check failed: ~S" ',form)))
|
||||
|
||||
(defun selections (candidate meal label)
|
||||
(remove-if-not
|
||||
(lambda (selection)
|
||||
(and (eql meal (organic-cafe::selection-meal selection))
|
||||
(eql label (organic-cafe::selection-label selection))))
|
||||
(organic-cafe::candidate-selections candidate)))
|
||||
|
||||
(defun check-within-budget (plans budget-cents)
|
||||
(check
|
||||
(every (lambda (candidate)
|
||||
(<= (organic-cafe::candidate-total candidate) budget-cents))
|
||||
plans)))
|
||||
|
||||
(defun test-peoples-organic ()
|
||||
(let* ((menu
|
||||
(organic-cafe:load-menu
|
||||
(menu-path "peoples-organic.sexp")))
|
||||
(candidates
|
||||
;; test a smaller budget to check filter
|
||||
(organic-cafe:feasible-candidates menu :full-day 85))
|
||||
(plans
|
||||
(organic-cafe:generate-plans
|
||||
menu :full-day 85 3
|
||||
:state (sb-ext:seed-random-state 1337))))
|
||||
(check (= 107168 (length candidates)))
|
||||
(check-within-budget candidates 8500)
|
||||
(check (= 3 (length plans)))
|
||||
(check-within-budget plans 8500)
|
||||
(length candidates)))
|
||||
|
||||
(defun test-townhall ()
|
||||
(let* ((menu
|
||||
(organic-cafe:load-menu
|
||||
(menu-path "townhall-shortnorth.sexp")))
|
||||
(plans
|
||||
(organic-cafe:generate-plans
|
||||
menu :full-day 70 3
|
||||
:state (sb-ext:seed-random-state 67)))
|
||||
(lazy-plan
|
||||
(first
|
||||
(organic-cafe:generate-plans
|
||||
menu :lazy-day 30 1
|
||||
:state (sb-ext:seed-random-state 69))))
|
||||
(branch-samples
|
||||
(organic-cafe:generate-plans
|
||||
menu :full-day 100 20
|
||||
:state (sb-ext:seed-random-state 69)
|
||||
:diversity-pool-size 1)))
|
||||
(check (= 3 (length plans)))
|
||||
(check-within-budget plans 7000)
|
||||
(dolist (candidate plans)
|
||||
(check (= 2 (length (selections candidate :lunch :side))))
|
||||
(check (= 2 (length (selections candidate :lunch :garnish))))
|
||||
(check
|
||||
(= 2
|
||||
(length
|
||||
(remove-duplicates
|
||||
(mapcar (lambda (selection)
|
||||
(organic-cafe::item-name
|
||||
(organic-cafe::selection-item selection)))
|
||||
(selections candidate :lunch :side))
|
||||
:test #'string=))))
|
||||
(let ((shared (selections candidate :dinner :shared-plate))
|
||||
(bowl (selections candidate :dinner :protein)))
|
||||
(check (not (and shared bowl)))
|
||||
(check (or shared bowl))
|
||||
(check shared)))
|
||||
(check (<= (organic-cafe::candidate-total lazy-plan) 3000))
|
||||
(check (= 4 (length
|
||||
(organic-cafe::candidate-selections lazy-plan))))
|
||||
(dolist (candidate branch-samples)
|
||||
(let ((shared (selections candidate :dinner :shared-plate))
|
||||
(bowl (selections candidate :dinner :protein)))
|
||||
(check (not (and shared bowl)))
|
||||
(check (or shared bowl))
|
||||
(when bowl
|
||||
(check (= 2 (length (selections candidate :dinner :side))))
|
||||
(check (= 2 (length
|
||||
(selections candidate :dinner :garnish)))))))
|
||||
;; At a roomy budget, both weighted dinner branches are reachable.
|
||||
(check
|
||||
(some (lambda (candidate)
|
||||
(selections candidate :dinner :shared-plate))
|
||||
branch-samples))
|
||||
(check
|
||||
(some (lambda (candidate)
|
||||
(selections candidate :dinner :protein))
|
||||
branch-samples))
|
||||
t))
|
||||
|
||||
(defun test-cli-lazy-day-budget ()
|
||||
(let* ((peoples-menu (menu-path "peoples-organic.sexp"))
|
||||
(output
|
||||
(with-output-to-string (stream)
|
||||
(let ((*standard-output* stream))
|
||||
(organic-cafe:run-cli
|
||||
(list "--days" "1"
|
||||
"--add-lazy-day" "30"
|
||||
"--seed" "1337")
|
||||
:default-menu peoples-menu)))))
|
||||
(check (search "Day 1" output))
|
||||
(check (search "Lazy Day (outbound)" output))
|
||||
(check (not (search "Lazy Day 2" output)))
|
||||
(check
|
||||
(handler-case
|
||||
(let ((*standard-output* (make-broadcast-stream)))
|
||||
(organic-cafe:run-cli
|
||||
(list "--days" "1"
|
||||
"--add-lazy-day" "1"
|
||||
"--seed" "1337")
|
||||
:default-menu peoples-menu)
|
||||
nil)
|
||||
(error (condition)
|
||||
(search "LAZY-DAY" (string-upcase
|
||||
(princ-to-string condition))))))
|
||||
(check
|
||||
(handler-case
|
||||
(progn
|
||||
(organic-cafe:run-cli
|
||||
(list "--plan" "lazy-day")
|
||||
:default-menu peoples-menu)
|
||||
nil)
|
||||
(error (condition)
|
||||
(search "--add-lazy-day"
|
||||
(princ-to-string condition)))))
|
||||
t))
|
||||
|
||||
(defun run-tests ()
|
||||
(let ((peoples-count (test-peoples-organic)))
|
||||
(test-townhall)
|
||||
(test-cli-lazy-day-budget)
|
||||
(format t
|
||||
"~&All organic-cafe tests passed (~:D enumerated People's days; TownHall DP sampling covered).~%"
|
||||
peoples-count)
|
||||
t))
|
||||
Reference in New Issue
Block a user