Browse code
Refactoring watch-stack for testability
Ed Langley authored on 13/04/2018 06:33:35
Showing 3 changed files
Showing 3 changed files
... | ... |
@@ -23,7 +23,8 @@ |
23 | 23 |
#:extract-timeline |
24 | 24 |
#:extract-list |
25 | 25 |
#:extract-stack |
26 |
- #:timeline)) |
|
26 |
+ #:timeline |
|
27 |
+ #:tagged-kv-formatter)) |
|
27 | 28 |
(in-package :cloud-watcher.aws-result) |
28 | 29 |
|
29 | 30 |
(defun find-all-indices (pred str &optional accum (start (or (car accum) 0))) |
... | ... |
@@ -55,13 +56,6 @@ |
55 | 56 |
(list (length v))))))) |
56 | 57 |
(serapeum:string-join parts "-"))) |
57 | 58 |
|
58 |
-(deftest decamelize () |
|
59 |
- (should be equal "a" (decamelize "A")) |
|
60 |
- (should be equal "a" (decamelize "a")) |
|
61 |
- (should be equal "outputs" (decamelize "Outputs")) |
|
62 |
- (should be equal "outputs-outputs" (decamelize "OutputsOutputs")) |
|
63 |
- (should be equal "a-b-c" (decamelize "ABC"))) |
|
64 |
- |
|
65 | 59 |
|
66 | 60 |
(defmacro tagged-kv-formatter (tag) |
67 | 61 |
`(formatter ,(format nil "~a ~~a ~~a~~%" tag))) |
... | ... |
@@ -156,3 +150,11 @@ |
156 | 150 |
(setf s-sdt (initialize-date s-sdt) |
157 | 151 |
s-edt (initialize-date s-edt) |
158 | 152 |
s-cdt (initialize-date s-cdt)))) |
153 |
+ |
|
154 |
+ |
|
155 |
+(deftest decamelize () |
|
156 |
+ (should be equal "a" (decamelize "A")) |
|
157 |
+ (should be equal "a" (decamelize "a")) |
|
158 |
+ (should be equal "outputs" (decamelize "Outputs")) |
|
159 |
+ (should be equal "outputs-outputs" (decamelize "OutputsOutputs")) |
|
160 |
+ (should be equal "a-b-c" (decamelize "ABC"))) |
... | ... |
@@ -3,7 +3,7 @@ |
3 | 3 |
(:import-from :cloud-watcher.aws-result :start-date-time :end-date-time) |
4 | 4 |
(:import-from :serapeum :op) |
5 | 5 |
(:import-from :clon :defsynopsis :group :flag :stropt) |
6 |
- (:use :cl) |
|
6 |
+ (:use :cl :st) |
|
7 | 7 |
(:export options |
8 | 8 |
#:*cloud-watcher-synopsis* |
9 | 9 |
#:dump)) |
... | ... |
@@ -20,6 +20,8 @@ |
20 | 20 |
(stropt :long-name "aws-region" :default-value "us-west-2") |
21 | 21 |
(flag :short-name "u" :long-name "update")) |
22 | 22 |
(group (:header "misc") |
23 |
+ (flag :long-name "rebuild") |
|
24 |
+ (flag :long-name "self-test") |
|
23 | 25 |
(flag :long-name "help")))) |
24 | 26 |
|
25 | 27 |
(defun stack-parameters-main (name) |
... | ... |
@@ -28,6 +30,23 @@ |
28 | 30 |
(defun stack-outputs-main (name) |
29 | 31 |
(stack-outputs (stack-for-name name))) |
30 | 32 |
|
33 |
+(defun run-tests () |
|
34 |
+ (st:test :package (find-package :cloud-watcher.aws-result)) |
|
35 |
+ (st:test :package (find-package :cloud-watcher.main)) |
|
36 |
+ (st:test :package (find-package :cloud-watcher.cli))) |
|
37 |
+ |
|
38 |
+(defun dump () |
|
39 |
+ "Create an executable with the command-line interface defined above." |
|
40 |
+ (handler-bind ((sb-ext:name-conflict (lambda (c) |
|
41 |
+ (declare (ignore c)) |
|
42 |
+ (invoke-restart-interactively 'sb-ext:resolve-conflict)))) |
|
43 |
+ (let ((sb-ext:*on-package-variance* '(:warn (:cloud-watcher.aws-result |
|
44 |
+ :cloud-watcher.main |
|
45 |
+ :cloud-watcher.cli) |
|
46 |
+ :error t))) |
|
47 |
+ (asdf:load-system :cloud-watcher :force t))) |
|
48 |
+ (clon:dump "cloud-watcher" main)) |
|
49 |
+ |
|
31 | 50 |
(defun main () |
32 | 51 |
(let* ((context (net.didierverna.clon:make-context :synopsis *cloud-watcher-synopsis*)) |
33 | 52 |
(files (clon:remainder :context context)) |
... | ... |
@@ -39,8 +58,6 @@ |
39 | 58 |
(cond ((clon:getopt :long-name "help") (clon:help)) |
40 | 59 |
((clon:getopt :long-name "watch") (cloud-watcher.main:watch-stack (car files))) |
41 | 60 |
((clon:getopt :long-name "outputs") (stack-outputs-main (car files))) |
42 |
- ((clon:getopt :long-name "parameters") (stack-parameters-main (car files)))))) |
|
43 |
- |
|
44 |
-(defun dump () |
|
45 |
- "Create an executable with the command-line interface defined above." |
|
46 |
- (clon:dump "cloud-watcher" main)) |
|
61 |
+ ((clon:getopt :long-name "parameters") (stack-parameters-main (car files))) |
|
62 |
+ ((clon:getopt :long-name "self-test") (run-tests)) |
|
63 |
+ ((clon:getopt :long-name "rebuild") (dump))))) |
... | ... |
@@ -43,27 +43,50 @@ |
43 | 43 |
(local-time-duration:timestamp-difference (end-date-time timeline) |
44 | 44 |
(start-date-time timeline)))) |
45 | 45 |
|
46 |
+(defun every-five-seconds (cb args &optional (delay-function #'sleep)) |
|
47 |
+ (loop |
|
48 |
+ while (apply cb args) |
|
49 |
+ do (funcall delay-function 5))) |
|
50 |
+ |
|
51 |
+(deftest every-five-seconds () |
|
52 |
+ (let ((counter 0) |
|
53 |
+ delay) |
|
54 |
+ (flet ((fake-delay (num) |
|
55 |
+ (incf counter) |
|
56 |
+ (setf delay num)) |
|
57 |
+ (work () |
|
58 |
+ (< counter 10))) |
|
59 |
+ (every-five-seconds #'work () #'fake-delay) |
|
60 |
+ (should be = 10 counter) |
|
61 |
+ (should be = 5 delay)))) |
|
62 |
+ |
|
63 |
+(defclass stack-watcher () |
|
64 |
+ ()) |
|
65 |
+ |
|
46 | 66 |
(defun watch-stack (name) |
47 | 67 |
(format t "~&Watching ~s~2%" name) |
48 |
- (let ((done? nil) |
|
49 |
- (old-status nil)) |
|
50 |
- (loop until done? |
|
51 |
- for the-stack = (stack-for-name name) |
|
52 |
- do |
|
53 |
- (unless old-status |
|
54 |
- (format t "~& PARAMETERS ~%============~%") |
|
55 |
- (stack-parameters the-stack) |
|
56 |
- (format t "~&============~2%")) |
|
57 |
- |
|
58 |
- (unless (eql old-status (stack-status the-stack)) |
|
59 |
- (format t "~&STATUS ~a~%" (stack-status the-stack)) |
|
60 |
- (setf old-status (stack-status the-stack))) |
|
61 |
- |
|
62 |
- (if (ends-with-subseq "COMPLETE" (symbol-name (stack-status the-stack))) |
|
63 |
- (progn |
|
64 |
- (format t "~2& OUTPUTS ~%=========~%") |
|
65 |
- (stack-outputs the-stack) |
|
66 |
- (format t "~&=========~%") |
|
67 |
- (return))) |
|
68 |
- (sleep 5))) |
|
68 |
+ (block nil |
|
69 |
+ (let ((old-status nil)) |
|
70 |
+ (every-five-seconds |
|
71 |
+ (lambda () |
|
72 |
+ (let* ((the-stack (stack-for-name name)) |
|
73 |
+ (current-status (stack-status the-stack))) |
|
74 |
+ (unless old-status |
|
75 |
+ (format t "~& PARAMETERS ~%============~%") |
|
76 |
+ (stack-parameters the-stack) |
|
77 |
+ (format t "~&============~2%")) |
|
78 |
+ |
|
79 |
+ (unless (eql old-status current-status) |
|
80 |
+ (format t "~&STATUS ~a~%" current-status) |
|
81 |
+ (setf old-status current-status)) |
|
82 |
+ |
|
83 |
+ (if (ends-with-subseq "COMPLETE" (symbol-name current-status)) |
|
84 |
+ (progn |
|
85 |
+ (format t "~2& OUTPUTS ~%=========~%") |
|
86 |
+ (stack-outputs the-stack) |
|
87 |
+ (format t "~&=========~%") |
|
88 |
+ nil) |
|
89 |
+ t))) |
|
90 |
+ ()))) |
|
69 | 91 |
(fresh-line)) |
92 |
+ |