Skip to content

Commit ac65dc8

Browse files
committed
Define tests
1 parent d5e43eb commit ac65dc8

File tree

3 files changed

+196
-4
lines changed

3 files changed

+196
-4
lines changed

Project.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ BitFlags = "d1d4a3ce-64b1-5f1a-9ba4-7e7e69966f35"
88
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
99
Mmap = "a63ad114-7e13-5084-954f-fe012c677804"
1010

11-
[compat]
12-
1311
[extras]
1412
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
1513

test/Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[deps]
2+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

test/runtests.jl

Lines changed: 194 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,198 @@
11
using UnixMmap
2+
using UnixMmap: mmap, PROT_READ, PROT_WRITE, MAP_PRIVATE, MAP_SHARED
23
using Test
34

4-
@testset "UnixMmap.jl" begin
5-
# Write your tests here.
5+
@testset "Mapping files by name" begin
6+
data = [zeros(Float64, 100); ones(Float64, 256)]
7+
byteoff = 100 * sizeof(Float64)
8+
9+
mktemp() do path, io
10+
write(io, zeros(Float64, 100))
11+
write(io, ones(Float64, 256))
12+
close(io)
13+
14+
# Open and read
15+
A = mmap(path, Array{Float64}, 356)
16+
@test A == data
17+
18+
# Open and read with offset
19+
A = mmap(path, Array{Float64}, 256; offset = byteoff)
20+
@test all(isone, A)
21+
22+
# File exists → opened by default as read-only
23+
@test_throws ReadOnlyMemoryError A[1] = 0.0
24+
25+
# Re-open with read-write permissions
26+
A = mmap(path, Array{Float64}, 256; offset = byteoff, prot = PROT_READ | PROT_WRITE)
27+
@test all(isone, A)
28+
A[1] = 2.0
29+
@test A[1] == 2.0
30+
A[1] = 1.0
31+
32+
# Unspecified length defaults to openening remainder of file
33+
A = mmap(path, Array{Float64}; offset = byteoff)
34+
@test length(A) == 256
35+
@test all(isone, A)
36+
# again without an offset
37+
A = mmap(path, Array{Float64})
38+
@test length(A) == length(data)
39+
@test A == data
40+
41+
# Unspecified array type defaults to UInt8
42+
A = mmap(path)
43+
@test A == reinterpret(UInt8, data)
44+
45+
A = nothing; GC.gc()
46+
end
47+
end
48+
49+
@testset "Mapping files by IO handle" begin
50+
data = [zeros(Float64, 100); ones(Float64, 256)]
51+
byteoff = 100 * sizeof(Float64)
52+
53+
mktemp() do path, io
54+
write(io, zeros(Float64, 100))
55+
write(io, ones(Float64, 256))
56+
close(io)
57+
58+
io = open(path, "r")
59+
# Open and read
60+
A = mmap(io, Array{Float64}, 356)
61+
@test A == data
62+
63+
# Open and read with offset
64+
A = mmap(io, Array{Float64}, 256; offset = byteoff)
65+
@test all(isone, A)
66+
67+
# File exists → opened by default as read-only
68+
@test_throws ReadOnlyMemoryError A[1] = 0.0
69+
70+
# File handle opened read-only, but requesting read-write
71+
@test_throws SystemError mmap(io, Array{Float64}, 256; prot = PROT_READ | PROT_WRITE)
72+
73+
# Reopen as read-write
74+
close(io)
75+
io = open(path, "r+")
76+
A = mmap(path, Array{Float64}, 256; offset = byteoff, prot = PROT_READ | PROT_WRITE)
77+
@test all(isone, A)
78+
A[1] = 2.0
79+
@test A[1] == 2.0
80+
A[1] = 1.0
81+
82+
# Unspecified length defaults to openening remainder of file
83+
A = mmap(io, Array{Float64}; offset = byteoff)
84+
@test length(A) == 256
85+
@test all(isone, A)
86+
# again without an offset
87+
A = mmap(io, Array{Float64})
88+
@test length(A) == length(data)
89+
@test A == data
90+
91+
# Unspecified array type defaults to UInt8
92+
A = mmap(io)
93+
@test A == reinterpret(UInt8, data)
94+
95+
close(io)
96+
A = nothing; GC.gc()
97+
end
98+
end
99+
100+
@testset "Growing mapped files" begin
101+
mktemp() do path, io
102+
close(io)
103+
@test filesize(path) == 0
104+
# Note! Require explicit write perms since the file `path` now exists
105+
A = mmap(path, Array{Float32}, 500; prot = PROT_READ | PROT_WRITE)
106+
@test filesize(path) == 2000
107+
@test all(iszero, A)
108+
end
109+
mktemp() do path, io
110+
close(io)
111+
@test filesize(path) == 0
112+
A = mmap(path, Array{Float32}, 500; offset = 400, prot = PROT_READ | PROT_WRITE)
113+
@test filesize(path) == 2400
114+
@test all(iszero, A)
115+
end
116+
mktemp() do path, io
117+
@test filesize(io) == 0
118+
# Here, `io` will have already been opened with write perms, so defaults OK
119+
A = mmap(io, Array{Float32}, 500)
120+
@test filesize(io) == 2000
121+
@test all(iszero, A)
122+
end
123+
mktemp() do path, io
124+
@test filesize(io) == 0
125+
A = mmap(io, Array{Float32}, 500; offset = 400)
126+
@test filesize(io) == 2400
127+
@test all(iszero, A)
128+
end
129+
130+
# If grow is *false*, the memory map cannot be accessed without throwing a
131+
# SIGBUS signal, but we can at least check that the file has not changed size.
132+
mktemp() do path, io
133+
@test filesize(io) == 0
134+
A = mmap(io, Array{Float32}, 500; offset = 400, grow = false)
135+
@test filesize(io) == 0
136+
A = nothing
137+
end
138+
139+
GC.gc()
140+
end
141+
142+
@testset "Shared and private file maps" begin
143+
data = collect(range(-1.0, stop=1.0, length=10))
144+
145+
# Default is shared mapping
146+
mktemp() do path, io
147+
write(io, data)
148+
flush(io)
149+
seek(io, 0)
150+
151+
A = mmap(io, Array{Float64})
152+
B = mmap(io, Array{Float64})
153+
154+
A[1] = 0.0
155+
@test B[1] == 0.0
156+
end
157+
158+
# Check that private mapping request works
159+
mktemp() do path, io
160+
write(io, data)
161+
flush(io)
162+
seek(io, 0)
163+
164+
A = mmap(io, Array{Float64}; flags = MAP_PRIVATE)
165+
B = mmap(io, Array{Float64}; flags = MAP_PRIVATE)
166+
167+
A[1] = 0.0
168+
@test B[1] == -1.0
169+
end
170+
end
171+
172+
@testset "Anonymous memory maps" begin
173+
A = mmap(Array{Int16}, 500)
174+
@test size(A) == (500,)
175+
176+
A = mmap(Array{Int16}, (50, 10))
177+
@test size(A) == (50, 10)
178+
end
179+
180+
@testset "In-core" begin
181+
A = mmap(Array{Int}, 5000)
182+
ic = UnixMmap.mincore(A)
183+
# Just checking that the function works
184+
@test ic isa Vector{Bool}
185+
186+
# On linux and if the array not immediately mapped by default, take the opportunity
187+
# to test for non-standard flag: MAP_POPULATE will force fully mapping into RAM
188+
if Sys.islinux() && any(!, ic)
189+
B = mmap(Array{Int}, 5000; flags = MAP_SHARED | UnixMmap.MAP_POPULATE)
190+
@test all(UnixMmap.mincore(B))
191+
end
192+
end
193+
194+
@testset "Giving advice" begin
195+
# It's hard to test behavior of the advise flags --- just check for not erroring
196+
A = mmap(Array{Int}, 500)
197+
@test A == UnixMmap.madvise!(A, UnixMmap.MADV_WILLNEED)
6198
end

0 commit comments

Comments
 (0)