aboutsummaryrefslogtreecommitdiff
path: root/spec/02-random_spec.lua
diff options
context:
space:
mode:
authorThijs Schreijer <thijs@thijsschreijer.nl>2026-02-13 14:49:50 +0100
committerThijs Schreijer <thijs@thijsschreijer.nl>2026-02-13 14:49:50 +0100
commitf6f0c77995fcd62863a7f24cbb407a68d2277759 (patch)
treee7713dd493c42404201f89993aa1513e224a53b6 /spec/02-random_spec.lua
parentdfd0d4b8ca3607ae39b1d2cbad4e3a7180dd6754 (diff)
downloadluasystem-f6f0c77995fcd62863a7f24cbb407a68d2277759.tar.gz
luasystem-f6f0c77995fcd62863a7f24cbb407a68d2277759.tar.bz2
luasystem-f6f0c77995fcd62863a7f24cbb407a68d2277759.zip
feat(random): add rnd() to mimic math.random()
Matches Lua 5.4+ implementation. But uses crypto secure random data.
Diffstat (limited to 'spec/02-random_spec.lua')
-rw-r--r--spec/02-random_spec.lua133
1 files changed, 133 insertions, 0 deletions
diff --git a/spec/02-random_spec.lua b/spec/02-random_spec.lua
index 23b6d95..db5d5ce 100644
--- a/spec/02-random_spec.lua
+++ b/spec/02-random_spec.lua
@@ -44,4 +44,137 @@ describe("Random:", function()
44 44
45 end) 45 end)
46 46
47
48
49 describe("rnd()", function()
50
51 local has_math_type = type(math.type) == "function"
52
53 it("with no args returns a number in [0, 1)", function()
54 local v, err = system.rnd()
55 assert.is_nil(err)
56 assert.is_number(v)
57 assert.is_true(v >= 0 and v < 1)
58 end)
59
60
61 it("with no args returns different values on multiple calls", function()
62 local seen = {}
63 for _ = 1, 20 do
64 local v = system.rnd()
65 seen[v] = true
66 end
67 local count = 0
68 for _ in pairs(seen) do count = count + 1 end
69 assert.is_true(count >= 2, "expected at least 2 distinct values in 20 calls")
70 end)
71
72
73 it("with one arg m returns integer in [1, m]", function()
74 for _ = 1, 50 do
75 local v, err = system.rnd(6)
76 assert.is_nil(err)
77 assert.is_true(v >= 1 and v <= 6 and math.floor(v) == v)
78 end
79 end)
80
81
82 it("matches math.random type behaviour for one-arg m when available", function()
83 if not has_math_type then
84 return
85 end
86 -- use math.random as ground truth for numeric type
87 local mval = math.random(6)
88 local rval = system.rnd(6)
89 assert.are.equal(math.type(mval), math.type(rval))
90 end)
91
92
93 it("with one arg 1 always returns 1", function()
94 for _ = 1, 10 do
95 local v, err = system.rnd(1)
96 assert.is_nil(err)
97 assert.are.equal(1, v)
98 end
99 end)
100
101
102 it("with one arg 0 returns a full-range integer", function()
103 local v, err = system.rnd(0)
104 assert.is_nil(err)
105 assert.is_true(type(v) == "number" or (math.type and math.type(v) == "integer"))
106 assert.is_true(v >= -0x8000000000000000 and v <= 0x7fffffffffffffff)
107 end)
108
109
110 it("matches math.random type behaviour for arg 0 when math.random(0) is supported", function()
111 if not has_math_type then
112 return
113 end
114 local ok, mval = pcall(math.random, 0)
115 if not ok then
116 return -- older Lua where math.random(0) is not supported
117 end
118 local rval = system.rnd(0)
119 assert.are.equal(math.type(mval), math.type(rval))
120 end)
121
122
123 it("with two args returns integer in [m, n]", function()
124 for _ = 1, 30 do
125 local v, err = system.rnd(10, 20)
126 assert.is_nil(err)
127 assert.is_true(v >= 10 and v <= 20 and math.floor(v) == v)
128 end
129 end)
130
131
132 it("matches math.random type behaviour for two-arg range when available", function()
133 if not has_math_type then
134 return
135 end
136 local mval = math.random(10, 20)
137 local rval = system.rnd(10, 20)
138 assert.are.equal(math.type(mval), math.type(rval))
139 end)
140
141
142 it("with two args supports negative range", function()
143 for _ = 1, 30 do
144 local v, err = system.rnd(-5, 5)
145 assert.is_nil(err)
146 assert.is_true(v >= -5 and v <= 5 and math.floor(v) == v)
147 end
148 end)
149
150
151 it("with two equal args returns that value", function()
152 local v, err = system.rnd(7, 7)
153 assert.is_nil(err)
154 assert.are.equal(7, v)
155 end)
156
157
158 it("returns nil and error for empty interval (m > n)", function()
159 local v, err = system.rnd(10, 5)
160 assert.is_falsy(v)
161 assert.are.equal("interval is empty", err)
162 end)
163
164
165 it("returns nil and error for invalid one-arg (m < 1, m ~= 0)", function()
166 local v, err = system.rnd(-1)
167 assert.is_falsy(v)
168 assert.are.equal("interval is empty", err)
169 end)
170
171
172 it("returns nil and error for wrong number of arguments", function()
173 local v, err = system.rnd(1, 2, 3)
174 assert.is_falsy(v)
175 assert.are.equal("wrong number of arguments", err)
176 end)
177
178 end)
179
47end) 180end)