Skip to content

Commit 4c41adf

Browse files
committed
test: fix png/freetype/mupdf unit tests
also add MD5 module
1 parent c14ffce commit 4c41adf

File tree

12 files changed

+391
-25
lines changed

12 files changed

+391
-25
lines changed

.busted

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
return {
2-
default = {
3-
verbose = true,
4-
ROOT = "spec/base/unit",
5-
},
2+
default = {
3+
verbose = true,
4+
ROOT = "spec/base/unit",
5+
lpath = "spec/base/unit/?.lua",
6+
},
67
}

.travis.yml

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,18 @@ before_install:
4242
- ln -s $(which gcc-4.8) bin/gcc
4343
- ln -s $(which c++-4.8) bin/c++
4444
- ln -s $(which g++-4.8) bin/g++
45-
# - curl "http://ftp.gnu.org/gnu/automake/automake-1.13.1.tar.gz" > automake-1.13.1.tar.gz
46-
# - tar -zxvf automake-1.13.1.tar.gz
47-
# - (cd automake-1.13.1 && ./configure --prefix=`pwd`/../ && make -j5 && make install)
4845
- export PATH=$PWD/bin:$PATH
4946

5047
install:
5148
- mkdir $HOME/.luarocks
5249
- cp /etc/luarocks/config.lua $HOME/.luarocks/config.lua
5350
- echo "wrap_bin_scripts = false" >> $HOME/.luarocks/config.lua
5451
# recent versions of busted may cause some weird segmentation faults
55-
- git clone https://github.com/Olivine-Labs/busted/
52+
# - git clone https://github.com/Olivine-Labs/busted/
5653
# - cd busted && git checkout v1.10.0 && luarocks --local make busted-1.10.0-0.rockspec && cd ..
57-
- cd busted && git checkout v2.0.rc11-0 && luarocks --local make busted-2.0.rc11-0.rockspec && cd ..
54+
- travis_retry luarocks --local install busted 2.0.rc11-0
55+
# for verbose_print module
56+
- travis_retry luarocks --local install ansicolors
5857
- eval $(luarocks path --bin)
5958
- export PATH=$PATH:$HOME/.luarocks/bin
6059

@@ -63,9 +62,14 @@ script:
6362
- make all
6463
- cp build/*/luajit $HOME/.luarocks/bin
6564
# install tesseract trained language data for testing OCR functionality
66-
- wget https://tesseract-ocr.googlecode.com/files/tesseract-ocr-3.02.eng.tar.gz
65+
- travis_retry wget https://tesseract-ocr.googlecode.com/files/tesseract-ocr-3.02.eng.tar.gz
6766
- tar zxf tesseract-ocr-3.02.eng.tar.gz
6867
- cd build/* && export TESSDATA_PREFIX=`pwd`/data && mkdir -p data/tessdata
6968
- mv ../../tesseract-ocr/tessdata/* data/tessdata/ && cd ../../
69+
# fetch font for base test
70+
- travis_retry wget https://github.com/koreader/koreader/raw/master/resources/fonts/droid/DroidSansMono.ttf
71+
- export OUTPUT_DIR=`ls -d ./build/x86_64-*linux-gnu`
72+
- mkdir -p ${OUTPUT_DIR}/fonts/droid/
73+
- cp DroidSansMono.ttf ${OUTPUT_DIR}/fonts/droid/DroidSansMono.ttf
7074
# finally make test
71-
- make test
75+
- travis_retry make test

Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ $(OUTPUT_DIR)/spec/base:
162162
ln -sf ../../../spec $(OUTPUT_DIR)/spec/base
163163

164164
test: $(OUTPUT_DIR)/spec $(OUTPUT_DIR)/.busted
165-
cd $(OUTPUT_DIR) && ./luajit $(shell which busted) ./spec/base/unit
165+
cd $(OUTPUT_DIR) && \
166+
./luajit $(shell which busted) \
167+
--exclude-tags=notest -o ./spec/base/unit/verbose_print ./spec/base/unit
166168

167169
.PHONY: test

ffi/MD5.lua

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
--[[--
2+
MD5 hash library.
3+
]]
4+
5+
local ffi = require "ffi"
6+
local bit = require "bit"
7+
local bxor = bit.bxor
8+
local bnot = bit.bnot
9+
local band = bit.band
10+
local bor = bit.bor
11+
local rshift = bit.rshift
12+
local lshift = bit.lshift
13+
local copy = ffi.copy
14+
local fill = ffi.fill
15+
16+
ffi.cdef[[
17+
typedef struct MD5Context {
18+
uint32_t buf[4];
19+
uint32_t bits[2];
20+
unsigned char input[64];
21+
} MD5_CTX;
22+
]]
23+
24+
local function byteReverse(buf, len)
25+
-- TODO: implement for big-endian architectures?
26+
end
27+
28+
local function F1(x, y, z) return bxor(z, band(x, bxor(y, z))) end
29+
local function F2(x, y, z) return F1(z, x, y) end
30+
local function F3(x, y, z) return bxor(x, y, z) end
31+
local function F4(x, y, z) return bxor(y, bor(x, bnot(z))) end
32+
33+
local function MD5STEP(f, w, x, y, z, data, s)
34+
w = w + f(x, y, z) + data
35+
w = bor(lshift(w,s), rshift(w,(32-s)))
36+
w = w + x
37+
38+
return w
39+
end
40+
41+
-- Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
42+
-- initialization constants.
43+
local function MD5Init(ctx)
44+
ctx.buf[0] = 0x67452301
45+
ctx.buf[1] = 0xefcdab89
46+
ctx.buf[2] = 0x98badcfe
47+
ctx.buf[3] = 0x10325476
48+
49+
ctx.bits[0] = 0
50+
ctx.bits[1] = 0
51+
end
52+
53+
local function MD5Transform(buf, input)
54+
local a = buf[0]
55+
local b = buf[1]
56+
local c = buf[2]
57+
local d = buf[3]
58+
59+
a = MD5STEP(F1, a, b, c, d, input[0] + 0xd76aa478, 7)
60+
d = MD5STEP(F1, d, a, b, c, input[1] + 0xe8c7b756, 12)
61+
c = MD5STEP(F1, c, d, a, b, input[2] + 0x242070db, 17)
62+
b = MD5STEP(F1, b, c, d, a, input[3] + 0xc1bdceee, 22)
63+
a = MD5STEP(F1, a, b, c, d, input[4] + 0xf57c0faf, 7)
64+
d = MD5STEP(F1, d, a, b, c, input[5] + 0x4787c62a, 12)
65+
c = MD5STEP(F1, c, d, a, b, input[6] + 0xa8304613, 17)
66+
b = MD5STEP(F1, b, c, d, a, input[7] + 0xfd469501, 22)
67+
a = MD5STEP(F1, a, b, c, d, input[8] + 0x698098d8, 7)
68+
d = MD5STEP(F1, d, a, b, c, input[9] + 0x8b44f7af, 12)
69+
c = MD5STEP(F1, c, d, a, b, input[10] + 0xffff5bb1, 17)
70+
b = MD5STEP(F1, b, c, d, a, input[11] + 0x895cd7be, 22)
71+
a = MD5STEP(F1, a, b, c, d, input[12] + 0x6b901122, 7)
72+
d = MD5STEP(F1, d, a, b, c, input[13] + 0xfd987193, 12)
73+
c = MD5STEP(F1, c, d, a, b, input[14] + 0xa679438e, 17)
74+
b = MD5STEP(F1, b, c, d, a, input[15] + 0x49b40821, 22)
75+
76+
a = MD5STEP(F2, a, b, c, d, input[1] + 0xf61e2562, 5)
77+
d = MD5STEP(F2, d, a, b, c, input[6] + 0xc040b340, 9)
78+
c = MD5STEP(F2, c, d, a, b, input[11] + 0x265e5a51, 14)
79+
b = MD5STEP(F2, b, c, d, a, input[0] + 0xe9b6c7aa, 20)
80+
a = MD5STEP(F2, a, b, c, d, input[5] + 0xd62f105d, 5)
81+
d = MD5STEP(F2, d, a, b, c, input[10] + 0x02441453, 9)
82+
c = MD5STEP(F2, c, d, a, b, input[15] + 0xd8a1e681, 14)
83+
b = MD5STEP(F2, b, c, d, a, input[4] + 0xe7d3fbc8, 20)
84+
a = MD5STEP(F2, a, b, c, d, input[9] + 0x21e1cde6, 5)
85+
d = MD5STEP(F2, d, a, b, c, input[14] + 0xc33707d6, 9)
86+
c = MD5STEP(F2, c, d, a, b, input[3] + 0xf4d50d87, 14)
87+
b = MD5STEP(F2, b, c, d, a, input[8] + 0x455a14ed, 20)
88+
a = MD5STEP(F2, a, b, c, d, input[13] + 0xa9e3e905, 5)
89+
d = MD5STEP(F2, d, a, b, c, input[2] + 0xfcefa3f8, 9)
90+
c = MD5STEP(F2, c, d, a, b, input[7] + 0x676f02d9, 14)
91+
b = MD5STEP(F2, b, c, d, a, input[12] + 0x8d2a4c8a, 20)
92+
93+
a = MD5STEP(F3, a, b, c, d, input[5] + 0xfffa3942, 4)
94+
d = MD5STEP(F3, d, a, b, c, input[8] + 0x8771f681, 11)
95+
c = MD5STEP(F3, c, d, a, b, input[11] + 0x6d9d6122, 16)
96+
b = MD5STEP(F3, b, c, d, a, input[14] + 0xfde5380c, 23)
97+
a = MD5STEP(F3, a, b, c, d, input[1] + 0xa4beea44, 4)
98+
d = MD5STEP(F3, d, a, b, c, input[4] + 0x4bdecfa9, 11)
99+
c = MD5STEP(F3, c, d, a, b, input[7] + 0xf6bb4b60, 16)
100+
b = MD5STEP(F3, b, c, d, a, input[10] + 0xbebfbc70, 23)
101+
a = MD5STEP(F3, a, b, c, d, input[13] + 0x289b7ec6, 4)
102+
d = MD5STEP(F3, d, a, b, c, input[0] + 0xeaa127fa, 11)
103+
c = MD5STEP(F3, c, d, a, b, input[3] + 0xd4ef3085, 16)
104+
b = MD5STEP(F3, b, c, d, a, input[6] + 0x04881d05, 23)
105+
a = MD5STEP(F3, a, b, c, d, input[9] + 0xd9d4d039, 4)
106+
d = MD5STEP(F3, d, a, b, c, input[12] + 0xe6db99e5, 11)
107+
c = MD5STEP(F3, c, d, a, b, input[15] + 0x1fa27cf8, 16)
108+
b = MD5STEP(F3, b, c, d, a, input[2] + 0xc4ac5665, 23)
109+
110+
a = MD5STEP(F4, a, b, c, d, input[0] + 0xf4292244, 6)
111+
d = MD5STEP(F4, d, a, b, c, input[7] + 0x432aff97, 10)
112+
c = MD5STEP(F4, c, d, a, b, input[14] + 0xab9423a7, 15)
113+
b = MD5STEP(F4, b, c, d, a, input[5] + 0xfc93a039, 21)
114+
a = MD5STEP(F4, a, b, c, d, input[12] + 0x655b59c3, 6)
115+
d = MD5STEP(F4, d, a, b, c, input[3] + 0x8f0ccc92, 10)
116+
c = MD5STEP(F4, c, d, a, b, input[10] + 0xffeff47d, 15)
117+
b = MD5STEP(F4, b, c, d, a, input[1] + 0x85845dd1, 21)
118+
a = MD5STEP(F4, a, b, c, d, input[8] + 0x6fa87e4f, 6)
119+
d = MD5STEP(F4, d, a, b, c, input[15] + 0xfe2ce6e0, 10)
120+
c = MD5STEP(F4, c, d, a, b, input[6] + 0xa3014314, 15)
121+
b = MD5STEP(F4, b, c, d, a, input[13] + 0x4e0811a1, 21)
122+
a = MD5STEP(F4, a, b, c, d, input[4] + 0xf7537e82, 6)
123+
d = MD5STEP(F4, d, a, b, c, input[11] + 0xbd3af235, 10)
124+
c = MD5STEP(F4, c, d, a, b, input[2] + 0x2ad7d2bb, 15)
125+
b = MD5STEP(F4, b, c, d, a, input[9] + 0xeb86d391, 21)
126+
127+
buf[0] = band(buf[0] + a, 0xFFFFFFFF)
128+
buf[1] = band(buf[1] + b, 0xFFFFFFFF)
129+
buf[2] = band(buf[2] + c, 0xFFFFFFFF)
130+
buf[3] = band(buf[3] + d, 0xFFFFFFFF)
131+
end
132+
133+
local function MD5Update(ctx, buf, len)
134+
local t
135+
136+
t = ctx.bits[0]
137+
ctx.bits[0] = t + lshift( len, 3)
138+
if (ctx.bits[0] < t) then
139+
ctx.bits[1] = ctx.bits[1] + 1
140+
end
141+
142+
ctx.bits[1] = ctx.bits[1] + rshift(len, 29)
143+
144+
t = band(rshift(t, 3), 0x3f)
145+
146+
if (t > 0) then
147+
local p = ffi.cast("unsigned char *", ctx.input + t)
148+
149+
t = 64 - t
150+
if (len < t) then
151+
copy(p, buf, len)
152+
return
153+
end
154+
155+
copy(p, buf, t)
156+
byteReverse(ctx.input, 16)
157+
MD5Transform(ctx.buf, ffi.cast("uint32_t *", ctx.input))
158+
buf = buf + t
159+
len = len - t
160+
end
161+
162+
while (len >= 64) do
163+
copy(ctx.input, buf, 64)
164+
byteReverse(ctx.input, 16)
165+
MD5Transform(ctx.buf, ffi.cast("uint32_t *", ctx.input))
166+
buf = buf + 64
167+
len = len - 64
168+
end
169+
170+
copy(ctx.input, buf, len)
171+
end
172+
173+
local function MD5Final(digest, ctx)
174+
175+
local count
176+
local p
177+
178+
count = band(rshift(ctx.bits[0], 3), 0x3F)
179+
180+
p = ctx.input + count
181+
p[0] = 0x80
182+
p = p + 1
183+
count = 64 - 1 - count
184+
185+
if (count < 8) then
186+
fill(p, count, 0)
187+
byteReverse(ctx.input, 16)
188+
MD5Transform(ctx.buf, ffi.cast("uint32_t *", ctx.input))
189+
fill(ctx.input, 56, 0)
190+
else
191+
fill(p, count - 8, 0)
192+
end
193+
194+
byteReverse(ctx.input, 14)
195+
196+
ffi.cast("uint32_t *", ctx.input)[14] = ctx.bits[0]
197+
ffi.cast("uint32_t *", ctx.input)[15] = ctx.bits[1]
198+
199+
MD5Transform(ctx.buf, ffi.cast("uint32_t *", ctx.input))
200+
byteReverse(ffi.cast("unsigned char *",ctx.buf), 4)
201+
copy(digest, ctx.buf, 16)
202+
fill(ffi.cast("char *", ctx), ffi.sizeof(ctx), 0)
203+
end
204+
205+
local hex = ffi.new("const char[16]", "0123456789abcdef")
206+
local function bin2str(output, input, len)
207+
if len > 0 then
208+
output[0] = hex[rshift(input[0], 4)]
209+
output[1] = hex[band(input[0], 0xF)]
210+
return bin2str(output+2, input+1, len-1)
211+
end
212+
end
213+
214+
215+
local md5_proto = {}
216+
md5_proto.__index = md5_proto
217+
218+
--- Feed content to md5 hashing instance.
219+
---- @string luastr stream to process
220+
function md5_proto:update(luastr)
221+
MD5Update(self.ctx, ffi.cast("const char*", luastr), #luastr)
222+
end
223+
224+
--- Calcualte md5 sum with the state of a md5 hashing instance.
225+
---- @string luastr stream to process
226+
---- @treturn string md5 sum in Lua string
227+
function md5_proto:sum(luastr)
228+
local buf = ffi.new("char[33]")
229+
local hash = ffi.new("uint8_t[16]")
230+
if luastr then
231+
self:update(luastr)
232+
end
233+
MD5Final(hash, self.ctx)
234+
235+
bin2str(buf, hash, ffi.sizeof(hash))
236+
return ffi.string(buf)
237+
end
238+
239+
240+
local md5 = {}
241+
242+
--- Create a new md5 hashing instance.
243+
---- @return md5 instance
244+
function md5.new()
245+
local o = {}
246+
o.ctx = ffi.new("MD5_CTX")
247+
MD5Init(o.ctx)
248+
setmetatable(o, md5_proto)
249+
return o
250+
end
251+
252+
--- Calcualte md5 sum.
253+
---- @string luastr stream to process
254+
---- @treturn string md5 sum in Lua string
255+
function md5.sum(luastr)
256+
return md5:new():sum(luastr)
257+
end
258+
259+
--- Calcualte md5 sum for a file.
260+
---- @string filename
261+
---- @treturn string md5 sum in Lua string
262+
function md5.sumFile(filename)
263+
local m = md5.new()
264+
local fd, err = io.open(filename, "rb")
265+
if err ~= nil then
266+
return nil, err
267+
end
268+
while true do
269+
local bytes = fd:read(8192)
270+
if not bytes then
271+
fd:close()
272+
break
273+
end
274+
m:update(bytes)
275+
end
276+
return m:sum()
277+
end
278+
279+
return md5

ffi/mupdf.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ function mupdf.openDocument(filename, cache_size)
8585
}
8686

8787
if mupdf_doc.doc == nil then
88-
merror("cannot open PDF file")
88+
merror("cannot open PDF file")
8989
end
9090

9191
setmetatable(mupdf_doc, document_mt)

spec/unit/data/simple-out.pdf

4 Bytes
Binary file not shown.

spec/unit/freetype_spec.lua

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ local Freetype = require("ffi/freetype")
22

33
describe("Freetype module", function()
44
it("should create new face without error", function()
5-
ok, face = pcall(Freetype.newFace, './fonts/droid/DroidSansMono.ttf',
6-
18)
7-
assert.True(ok)
8-
assert.are_not.equals(face, nil)
5+
assert.has_no.errors(function()
6+
local face = Freetype.newFace('./fonts/droid/DroidSansMono.ttf', 18)
7+
assert.are_not.equals(face, nil)
8+
end)
99
end)
1010
end)

0 commit comments

Comments
 (0)