Skip to content

Commit b15fe07

Browse files
committed
feat: add a bunch more unit tests
1 parent c0c1d4d commit b15fe07

File tree

2 files changed

+205
-2
lines changed

2 files changed

+205
-2
lines changed

spec/main_spec.lua

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,212 @@
1+
---@diagnostic disable: discard-returns
2+
-- TODO: @diagnostic disable: missing-parameter, param-type-mismatch
13
describe('fensteraudio', function()
24
local fensteraudio = require('fensteraudio')
35

6+
describe('fensteraudio.samplerate', function()
7+
it('should be an integer and one of the common sample rates', function()
8+
local common_sample_rates = {
9+
[8000] = true, [11025] = true, [16000] = true, [22050] = true, [32000] = true, [44100] = true, [48000] = true,
10+
[88200] = true, [96000] = true, [176400] = true, [192000] = true, [352800] = true, [384000] = true,
11+
}
12+
13+
assert.is_number(fensteraudio.samplerate)
14+
assert.is_true(common_sample_rates[fensteraudio.samplerate])
15+
end)
16+
end)
17+
18+
describe('fensteraudio.buffersize', function()
19+
it('should be an integer and a power of 2', function()
20+
assert.is_number(fensteraudio.buffersize)
21+
assert.is_true(fensteraudio.buffersize > 0)
22+
local x = math.log(fensteraudio.buffersize) / math.log(2)
23+
assert.is_true(x == math.floor(x))
24+
end)
25+
end)
26+
427
describe('fensteraudio.open(...)', function()
528
it('should return a audiodevice userdata #needsspeaker', function()
629
local audiodevice = fensteraudio.open()
730
finally(function() audiodevice:close() end)
831
assert.is_userdata(audiodevice)
932
end)
1033
end)
34+
35+
describe('audiodevice:close(...) / fensteraudio.close(...)', function()
36+
it('should throw when no arguments were given when not using as method', function()
37+
assert.has_error(function() fensteraudio.close() end)
38+
end)
39+
40+
it('should throw when audiodevice is not a audiodevice userdata when not using as method', function()
41+
assert.has_error(function() fensteraudio.close(25) end)
42+
assert.has_error(function() fensteraudio.close(2.5) end)
43+
assert.has_error(function() fensteraudio.close('ERROR') end)
44+
assert.has_error(function() fensteraudio.close(true) end)
45+
assert.has_error(function() fensteraudio.close({}) end)
46+
assert.has_error(function() fensteraudio.close(function() end) end)
47+
assert.has_error(function() fensteraudio.close(io.stdout) end)
48+
end)
49+
50+
it('should throw when audiodevice is used after closing #needsspeaker', function()
51+
local audiodevice = fensteraudio.open()
52+
fensteraudio.close(audiodevice)
53+
assert.has_error(function() fensteraudio.close(audiodevice) end)
54+
assert.has_error(function() fensteraudio.available(audiodevice) end)
55+
assert.has_error(function() fensteraudio.write(audiodevice, { 0 }) end)
56+
57+
local audiodevice2 = fensteraudio.open()
58+
audiodevice2:close()
59+
assert.has_error(function() audiodevice2:close() end)
60+
assert.has_error(function() audiodevice2:available() end)
61+
assert.has_error(function() audiodevice2:write({ 0 }) end)
62+
end)
63+
end)
64+
65+
describe('audiodevice:available(...) / fensteraudio.available(...)', function()
66+
it('should throw when no arguments were given when not using as method', function()
67+
assert.has_error(function() fensteraudio.available() end)
68+
end)
69+
70+
it('should throw when audiodevice is not a audiodevice userdata when not using as method', function()
71+
assert.has_error(function() fensteraudio.available(25) end)
72+
assert.has_error(function() fensteraudio.available(2.5) end)
73+
assert.has_error(function() fensteraudio.available('ERROR') end)
74+
assert.has_error(function() fensteraudio.available(true) end)
75+
assert.has_error(function() fensteraudio.available({}) end)
76+
assert.has_error(function() fensteraudio.available(function() end) end)
77+
assert.has_error(function() fensteraudio.available(io.stdout) end)
78+
end)
79+
80+
it('should return an integer #needsspeaker', function()
81+
local audiodevice = fensteraudio.open()
82+
finally(function() audiodevice:close() end)
83+
84+
assert.is_number(fensteraudio.available(audiodevice))
85+
assert.is_number(audiodevice:available())
86+
end)
87+
end)
88+
89+
describe('audiodevice:write(...) / fensteraudio.write(...)', function()
90+
it('should throw when no arguments were given when not using as method', function()
91+
assert.has_error(function() fensteraudio.write() end)
92+
end)
93+
94+
it('should throw when audiodevice is not a audiodevice userdata when not using as method', function()
95+
assert.has_error(function() fensteraudio.write(25, { 0 }) end)
96+
assert.has_error(function() fensteraudio.write(2.5, { 0 }) end)
97+
assert.has_error(function() fensteraudio.write('ERROR', { 0 }) end)
98+
assert.has_error(function() fensteraudio.write(true, { 0 }) end)
99+
assert.has_error(function() fensteraudio.write({}, { 0 }) end)
100+
assert.has_error(function() fensteraudio.write(function() end, { 0 }) end)
101+
assert.has_error(function() fensteraudio.write(io.stdout, { 0 }) end)
102+
end)
103+
104+
it('should throw when samples is not a table #needsspeaker', function()
105+
local audiodevice = fensteraudio.open()
106+
finally(function() audiodevice:close() end)
107+
108+
assert.has_error(function() fensteraudio.write(audiodevice, 'ERROR') end)
109+
assert.has_error(function() fensteraudio.write(audiodevice, true) end)
110+
assert.has_error(function() fensteraudio.write(audiodevice, function() end) end)
111+
assert.has_error(function() fensteraudio.write(audiodevice, io.stdout) end)
112+
assert.has_error(function() fensteraudio.write(audiodevice, 0) end)
113+
assert.has_error(function() fensteraudio.write(audiodevice, 2.5) end)
114+
115+
assert.has_error(function() audiodevice:write('ERROR') end)
116+
assert.has_error(function() audiodevice:write(true) end)
117+
assert.has_error(function() audiodevice:write(function() end) end)
118+
assert.has_error(function() audiodevice:write(io.stdout) end)
119+
assert.has_error(function() audiodevice:write(0) end)
120+
assert.has_error(function() audiodevice:write(2.5) end)
121+
end)
122+
123+
it('should throw when one of the samples is not a number #needsspeaker', function()
124+
local audiodevice = fensteraudio.open()
125+
finally(function() audiodevice:close() end)
126+
127+
assert.has_error(function() fensteraudio.write(audiodevice, { 'ERROR' }) end)
128+
assert.has_error(function() fensteraudio.write(audiodevice, { true }) end)
129+
assert.has_error(function() fensteraudio.write(audiodevice, { function() end }) end)
130+
assert.has_error(function() fensteraudio.write(audiodevice, { io.stdout }) end)
131+
assert.has_error(function() fensteraudio.write(audiodevice, { 0, 0, 'zero', 0, 0 }) end)
132+
133+
assert.has_error(function() audiodevice:write({ 'ERROR' }) end)
134+
assert.has_error(function() audiodevice:write({ true }) end)
135+
assert.has_error(function() audiodevice:write({ function() end }) end)
136+
assert.has_error(function() audiodevice:write({ io.stdout }) end)
137+
assert.has_error(function() audiodevice:write({ 0, 0, 'zero', 0, 0 }) end)
138+
end)
139+
140+
it('should throw when samplesend is not an integer #needsspeaker', function()
141+
local audiodevice = fensteraudio.open()
142+
finally(function() audiodevice:close() end)
143+
144+
assert.has_error(function() fensteraudio.write(audiodevice, { 0 }, 'ERROR') end)
145+
assert.has_error(function() fensteraudio.write(audiodevice, { 0 }, true) end)
146+
assert.has_error(function() fensteraudio.write(audiodevice, { 0 }, {}) end)
147+
assert.has_error(function() fensteraudio.write(audiodevice, { 0 }, function() end) end)
148+
assert.has_error(function() fensteraudio.write(audiodevice, { 0 }, io.stdout) end)
149+
assert.has_error(function() fensteraudio.write(audiodevice, { 0 }, 2.5) end)
150+
151+
assert.has_error(function() audiodevice:write({ 0 }, 'ERROR') end)
152+
assert.has_error(function() audiodevice:write({ 0 }, true) end)
153+
assert.has_error(function() audiodevice:write({ 0 }, {}) end)
154+
assert.has_error(function() audiodevice:write({ 0 }, function() end) end)
155+
assert.has_error(function() audiodevice:write({ 0 }, io.stdout) end)
156+
assert.has_error(function() audiodevice:write({ 0 }, 2.5) end)
157+
end)
158+
159+
it('should throw when samples are too many #needsspeaker', function()
160+
local audiodevice = fensteraudio.open()
161+
finally(function() audiodevice:close() end)
162+
163+
local samples = {}
164+
for _ = 1, fensteraudio.buffersize + 1 do
165+
table.insert(samples, 0)
166+
end
167+
168+
assert.has_error(function() fensteraudio.write(audiodevice, samples) end)
169+
170+
assert.has_error(function() audiodevice:write(samples) end)
171+
end)
172+
173+
it('should throw when one of the samples is out of range #needsspeaker', function()
174+
local audiodevice = fensteraudio.open()
175+
finally(function() audiodevice:close() end)
176+
177+
assert.has_error(function() fensteraudio.write(audiodevice, { 0, 1.1, 0 }) end)
178+
assert.has_error(function() fensteraudio.write(audiodevice, { 0, -1.1, 0 }) end)
179+
180+
assert.has_error(function() audiodevice:write({ 0, 1.1, 0 }) end)
181+
assert.has_error(function() audiodevice:write({ 0, -1.1, 0 }) end)
182+
end)
183+
184+
it('should throw when samplesend is out of range #needsspeaker', function()
185+
local audiodevice = fensteraudio.open()
186+
finally(function() audiodevice:close() end)
187+
188+
assert.has_error(function() fensteraudio.write(audiodevice, { 0 }, -1) end)
189+
assert.has_error(function() fensteraudio.write(audiodevice, { 0 }, 2) end)
190+
191+
assert.has_error(function() audiodevice:write({ 0 }, -1) end)
192+
assert.has_error(function() audiodevice:write({ 0 }, 2) end)
193+
end)
194+
195+
it('should write a sample successfully #needsspeaker', function()
196+
local audiodevice = fensteraudio.open()
197+
finally(function() audiodevice:close() end)
198+
199+
fensteraudio.write(audiodevice, { 0 })
200+
fensteraudio.write(audiodevice, { 0 }, 1)
201+
fensteraudio.write(audiodevice, { 0, 0.1, 0, -0.1, 0 }, 3)
202+
203+
audiodevice:write({ 0 })
204+
audiodevice:write({ 0 }, 1)
205+
audiodevice:write({ 0, 0.1, 0, -0.1, 0 }, 3)
206+
end)
207+
208+
it('should allow table-like objects for samples', function ()
209+
assert.is_true(true)
210+
end)
211+
end)
11212
end)

src/main.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,15 +215,17 @@ static int audiodevice_write(lua_State *L) {
215215
audiodevice *p_audiodevice = check_open_audiodevice(L);
216216
lua_Integer samples_length = check_samples(L);
217217
lua_Integer samples_end = luaL_optinteger(L, 3, samples_length);
218-
luaL_argcheck(L, samples_end <= samples_length, 3,
219-
"end index must be less than or equal to the samples length");
218+
luaL_argcheck(L, samples_end >= 0 && samples_end <= samples_length, 3,
219+
"end index must be in the range of 0 to less than or equal to the samples length");
220220

221221
// read samples from the table
222222
int is_number;
223223
for (lua_Integer i = 0; i < samples_end; i++) {
224224
lua_geti(L, 2, i + 1);
225225
p_audiodevice->samples[i] = (float)lua_tonumberx(L, -1, &is_number);
226226
luaL_argcheck(L, is_number, 2, "samples must be a table of numbers");
227+
luaL_argcheck(L, p_audiodevice->samples[i] >= -1.0f && p_audiodevice->samples[i] <= 1.0f, 2,
228+
"samples must be in the range of -1.0 to 1.0");
227229
lua_pop(L, 1);
228230
}
229231

0 commit comments

Comments
 (0)