Skip to content

Commit

Permalink
[tests] add test case for cligen formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
Vindaar committed Feb 22, 2024
1 parent ab94966 commit 2d60fa3
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 0 deletions.
1 change: 1 addition & 0 deletions measuremancer.nimble
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ task testDeps, "Installs dependencies for tests":

task test, "Run standard tests":
exec "nim c -r tests/tmeasuremancer.nim"
exec "nim c -d:release -d:useCligen -r tests/tCligenParsing.nim"
68 changes: 68 additions & 0 deletions tests/tCligenParsing.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import std / random
## This is just a short program to generate numbers (value ± uncertainty),
## format them with `cligen` and verify that the formatting is what we expect, given
## the uncertainties and the required precision.
import measuremancer
import std / strscans

# How many digits the error may be smaller than the value in OOM
const N_smaller = 6
const Total = 1_000_000
for i in 0 ..< Total:
if i mod 50_000 == 0:
echo "i = ", i, " / ", Total
# 1. sample exponents
let expVal = rand(-300 .. 300)
# 1b. exponent up to N digits smaller
let expErrDiff = rand(0 .. N_smaller)
# 2. sample a value and an eror
let valNoExp = rand(0.1 .. 1.0)
let errNoExp = rand(0.1 .. 1.0)
# 3. combine value and error
let val = valNoExp * 10 * pow(10.0, (expVal).float)
let err = errNoExp * 10 * pow(10.0, (expVal - expErrDiff).float)
# 4. -> make a 'Measurement'
let meas = val ± err
# 5. sample a precision
let prec = rand(1 .. 16)
let resStr = pretty(meas, precision = prec, merge = true)
# 6. verify the produced string
#echo val, " ± ", err, " = ", resStr, " prec = ", prec
# Note that we parse digits after `.` and precision as strings. Might exceed `int.high` and we don't
# want to add an additional int ⇔ string conversion
let (success, digit, numbers, uncert, exp) = scanTuple(resStr, "$i.$+($+)e$i")
if success:
# 1. verify precision in parenthesis. Must be number of digits given by `prec`
doAssert (uncert).len == prec, ("Need: " & $prec & " got: " & $uncert)
# 2. determine difference in exponent after possible rounding
var expErrReal = expErrDiff
# 2a. check if rounding of error affects difference
let errNoExpRound = errNoExp.round(prec) # Rounding of error can affect rounding of value
if errNoExpRound == 1.0: # increased by OOM, adjust difference in exponent
expErrReal -= 1
# 2b. round according to (possibly) updated exp difference...
let valNoExpRound = valNoExp.round(expErrReal + prec) # use final exponent difference and precision to round
let valueRound = expErrReal + prec # store this value to round integer by
# 2c. and possibly adjust exponent difference
if valNoExpRound == 1.0: # increased by OOM, adjust exp difference
expErrReal += 1
#echo valNoExpRound, " vs ", valNoExp, " and ", errNoExpRound, " vs ", errNoExp
# 2d. `-1` for one significant digit in front of `.`
expErrReal -= 1
let numDigits = min(expErrReal + prec, 18) # maximum precision: 18
#echo "expErrDiff ", expErrDiff, " expErrReal ", expErrReal, " prec ", prec, " numDigits ", numDigits, " numbers: ", numbers.len
#echo "REAL EXP: ", expErrDiff + prec - 1
doAssert numDigits == numbers.len, ("Need: " & $numDigits & " got: " & $numbers.len)
# 3. verify exponent
let expValReal = if valNoExpRound == 1.0: expVal + 1 else: expVal # if value rounded up!
doAssert exp == expValReal, ("Need: " & $expValReal & " got: " & $exp)
# 4. verify digit in front of `.`
var intDigit = ((valNoExp * 10.0).round(valueRound - 1)).trunc.int
if intDigit == 10:
intDigit = 1
doAssert intDigit == digit, "Got " & $digit & " expected " & $intDigit

if not success: ## Cases without `e` notation
# HANDLE THES
#echo success, " res ", resStr
discard

0 comments on commit 2d60fa3

Please sign in to comment.