From dc906585b26adfc928c10f3f641d2f970e75eed4 Mon Sep 17 00:00:00 2001 From: David Byers <david.byers@liu.se> Date: Thu, 23 Jul 2020 18:30:19 +0200 Subject: [PATCH] Add type and range checks to public functions. --- CHANGELOG | 7 +++ olc.el | 41 ++++++++++++++---- test/olctest.el | 112 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+), 8 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index c9ae479..95e5b58 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,12 @@ 2020-07-23 David Byers <david.byers@liu.se> + Fix issue #2: + * olc.el (olc-parse-code): Add type checks. + (olc-encode): Add type checks. + (olc-shorten): Add type checks. + (olc-shorten-compound): Add type and range checks. + (olc-recover): Add type checks. + Fix issue #3: * olc.el (olc-parse-code): Save match data. (olc-is-valid): Save match data. diff --git a/olc.el b/olc.el index 3be5a31..fa26870 100644 --- a/olc.el +++ b/olc.el @@ -3,7 +3,7 @@ ;; Copyright (C) 2020 David Byers ;; ;; Author: David Byers <david.byers@liu.se> -;; Version: 1.0.1 +;; Version: 1.0.2 ;; Package-Requires: ((emacs "25.1")) ;; Keywords: extensions, lisp ;; URL: https://gitlab.liu.se/davby02/olc @@ -165,10 +165,11 @@ raise, and args for the raised error. (expt 20 (- (floor (+ 2 (/ len 2))))) (/ (expt 20 -3) (expt 5 (- len 10))))) -(defun olc-parse-code (code) +(cl-defun olc-parse-code (code) "Parse an open location code CODE." (if (olc-parse-p code) code + (cl-check-type code stringp) (save-match-data (let ((pos 0) (pairs nil) @@ -344,6 +345,10 @@ LEN is automatically clipped to between 2 and 15. Returns an olc-area structure. Raises olc-encode-error if the values cannot (legally) be encoded to the selected length." + (cl-check-type lat number) + (cl-check-type lon number) + (cl-check-type len integer) + (setq len (max 2 (min 15 len))) (when (and (< len 11) (/= (% len 2) 0)) (signal 'olc-encode-error "invalid encoding length")) @@ -445,11 +450,12 @@ specified, then the code will be shortened by at most that many digits. If the code can't be shortened, the original code is returned. `olc-shorten-error' is raised if CODE is a padded or shortened code, of if LIMIT is not positive and even." + (cl-check-type lat number) + (cl-check-type lon number) + (cl-check-type limit (member 2 4 6 8 10 12)) + (let* ((parse (olc-parse-code code)) (area (olc-decode parse))) - (unless (and (> limit 0) (= 0 (% limit 2))) - (signal 'olc-shorten-error - (list "limit must be even and positive" code))) (when (olc-is-short parse) (signal 'olc-shorten-error (list "can't shorten shortened codes" code))) @@ -493,15 +499,29 @@ it can take some time to complete. If you can set the zoom level to a single number, then it will make one call only, and is much faster. " + (cl-check-type code stringp) + (cl-check-type limit (member 2 4 6 8 10 12)) + (cl-check-type zoom (or integer listp)) + (save-match-data (let* ((area (olc-decode code)) (zoom-lo (cond ((numberp zoom) zoom) ((listp zoom) (elt zoom 0)) (t (signal 'args-out-of-range zoom)))) - (zoom-hi (cond ((numberp zoom) (1+ zoom)) - ((listp zoom) (1+ (elt zoom 1))) + (zoom-hi (cond ((numberp zoom) zoom) + ((listp zoom) (elt zoom 1)) (t (signal 'args-out-of-range zoom)))) result) + + ;; Check that zoom range is not inverted + (when (or (< zoom-hi zoom-lo) + (< zoom-hi 1) (> zoom-hi 18) + (< zoom-lo 1) (> zoom-lo 18)) + (signal 'args-out-of-range zoom)) + + ;; Otherwise we may never hit the high limit + (setq zoom-hi (1+ zoom-hi)) + (catch 'result (while (< zoom-lo zoom-hi) (let* ((zoom (floor (+ zoom-lo zoom-hi) 2)) @@ -552,6 +572,11 @@ center of the recovered area (LATITUDE . LONGITUDE) is returned. If FORMAT is `area' (or any other value), the returned value is an full open location code." + (cl-check-type code stringp) + (cl-check-type lat number) + (cl-check-type lon number) + (cl-check-type format (member area latlon)) + (let ((parse (olc-parse-code code))) (if (olc-is-full parse) (if (eq format 'latlon) @@ -601,7 +626,7 @@ full open location code." ;; Check types (defer check of ref) (cl-check-type code stringp) - (cl-check-type format (member latlon area nil)) + (cl-check-type format (member latlon area)) ;; Process code and check ref (cond ((string-match "^\\(\\S-+\\)\\s-+\\(.*\\)$" code) diff --git a/test/olctest.el b/test/olctest.el index 7a8e51d..0e0f4db 100644 --- a/test/olctest.el +++ b/test/olctest.el @@ -261,6 +261,117 @@ :act (olc-is-short "+12345678") :msg "S3"))) +(defun olctest-issue-2 () + (olctest-testcase "local:issue-2" + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-parse-code") + (olc-parse-code nil)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-is-valid") + (olc-is-valid nil)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-is-short") + (olc-is-short nil)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-is-full") + (olc-is-full nil)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-code-precision") + (olc-code-precision nil)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-encode:lat") + (olc-encode nil 1)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-encode:lon") + (olc-encode 1 nil)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-encode:key") + (olc-encode 1 1 :len nil)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-decode") + (olc-decode nil)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-shorten:code") + (olc-shorten nil 1 1)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-shorten:lat") + (olc-shorten "" nil 1)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-shorten:lon") + (olc-shorten "" 1 nil)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-shorten:limit:nil") + (olc-shorten "" 1 nil)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-shorten:limit:lo") + (olc-shorten "" 1 1 :limit 0)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-shorten:limit:hi") + (olc-shorten "" 1 1 :limit 19)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-shorten:limit:odd") + (olc-shorten "" 1 1 :limit 3)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-shorten-compound:code:nil") + (olc-shorten-compound nil)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-shorten-compound:limit:nil") + (olc-shorten-compound "22222222+" :limit nil)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-shorten-compound:limit:lo") + (olc-shorten-compound "22222222+" :limit 0)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-shorten-compound:limit:hi") + (olc-shorten-compound "22222222+" :limit 19)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-shorten-compound:limit:odd") + (olc-shorten-compound "22222222+" :limit 3)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-shorten-compound:zoom:nil") + (olc-shorten-compound "22222222+" :zoom nil)) + + (olctest-assert-error (:exp (args-out-of-range) :msg "olc-shorten-compound:zoom:lo") + (olc-shorten-compound "22222222+" :zoom 0)) + + (olctest-assert-error (:exp (args-out-of-range) :msg "olc-shorten-compound:zoom:hi") + (olc-shorten-compound "22222222+" :zoom 19)) + + (olctest-assert-error (:exp (args-out-of-range) :msg "olc-shorten-compound:zoom:llo") + (olc-shorten-compound "22222222+" :zoom '(0 8))) + + (olctest-assert-error (:exp (args-out-of-range) :msg "olc-shorten-compound:zoom:rhi") + (olc-shorten-compound "22222222+" :zoom '(1 19))) + + (olctest-assert-error (:exp (args-out-of-range) :msg "olc-shorten-compound:zoom:inv") + (olc-shorten-compound "22222222+" :zoom '(5 4))) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-recover:code") + (olc-recover nil 1 1)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-recover:lat") + (olc-recover "" nil 1)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-recover:lon") + (olc-recover "" 1 nil)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-recover:format") + (olc-recover "22222222+" 1 1 :format 'invalid)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-recover-compound:code") + (olc-recover-compound nil :ref "Stockholm")) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-recover-compound:ref:double") + (olc-recover-compound "2222+ Stockholm" :ref "Stockholm")) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-recover-compound:ref:nil") + (olc-recover-compound "2222+" :ref nil)) + + (olctest-assert-error (:exp (wrong-type-argument) :msg "olc-recover-compound:format") + (olc-recover-compound "2222+" :ref "Stockholm" :format 'invalid)) + + )) + + + (defun olctest-issue-1 () (olctest-testcase "local:issue-1" (olctest-assert-error (:exp (wrong-type-argument) :msg "F1") @@ -310,6 +421,7 @@ (olctest-validity) (olctest-localtests) (olctest-issue-3) + (olctest-issue-2) (olctest-issue-1) )) -- GitLab