1#	$NetBSD: t_call_once.sh,v 1.6 2022/06/12 15:08:38 skrll Exp $
2#
3# Copyright (c) 2018 The NetBSD Foundation, Inc.
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25# POSSIBILITY OF SUCH DAMAGE.
26#
27
28atf_test_case call_once
29call_once_head() {
30	atf_set "descr" "compile and run std::call_once"
31	atf_set "require.progs" "c++"
32}
33
34atf_test_case call_once_profile
35call_once_profile_head() {
36	atf_set "descr" "compile and run std::call_once with profiling option"
37	atf_set "require.progs" "c++"
38}
39
40atf_test_case call_once_pic
41call_once_pic_head() {
42	atf_set "descr" "compile and run PIC std::call_once"
43	atf_set "require.progs" "c++"
44}
45
46atf_test_case call_once_pic_32
47call_once_pic_32_head() {
48	atf_set "descr" "compile and run 32-bit PIC std::call_once"
49	atf_set "require.progs" "c++"
50}
51
52atf_test_case call_once_pic_profile
53call_once_pic_head() {
54	atf_set "descr" "compile and run PIC std::call_once with profiling flag"
55	atf_set "require.progs" "c++"
56}
57
58atf_test_case call_once_pic_profile_32
59call_once_pic_profile_32_head() {
60	atf_set "descr" "compile and run 32-bit PIC std::call_once with profiling flag"
61	atf_set "require.progs" "c++"
62}
63
64atf_test_case call_once_profile_32
65call_once_profile_32_head() {
66	atf_set "descr" "compile and run 32-bit std::call_once with profiling flag"
67	atf_set "require.progs" "c++"
68}
69
70atf_test_case call_once_pie
71call_once_pie_head() {
72	atf_set "descr" "compile and run position independent (PIE) std::call_once"
73	atf_set "require.progs" "c++"
74}
75
76atf_test_case call_once_32
77call_once_32_head() {
78	atf_set "descr" "compile and run std::call_once for/in netbsd32 emulation"
79	atf_set "require.progs" "c++ file diff cat"
80}
81
82atf_test_case call_once_static
83call_once_static_head() {
84	atf_set "descr" "compile and run std::call_once with static flag"
85	atf_set "require.progs" "c++"
86}
87
88call_once_body() {
89	cat > test.cpp << EOF
90#include <cstdio>
91#include <thread>
92#include <mutex>
93std::once_flag flag;
94int main(void) {
95        std::call_once(flag, [](){ printf("hello, world!\n"); });
96        return 0;
97}
98EOF
99	atf_check -s exit:0 -o ignore -e ignore c++ -o call_once test.cpp -pthread
100	atf_check -s exit:0 -o inline:"hello, world!\n" ./call_once
101}
102
103call_once_profile_body() {
104	cat > test.cpp << EOF
105#include <cstdio>
106#include <thread>
107#include <mutex>
108std::once_flag flag;
109int main(void) {
110        std::call_once(flag, [](){ printf("hello, world!\n"); });
111        return 0;
112}
113EOF
114	atf_check -s exit:0 -o ignore -e ignore c++ -static -pg -o call_once test.cpp -pthread
115	atf_check -s exit:0 -o inline:"hello, world!\n" ./call_once
116}
117
118call_once_profile_32_body() {
119	# check whether this arch is 64bit
120	if ! c++ -dM -E - < /dev/null | fgrep -q _LP64; then
121		atf_skip "this is not a 64 bit architecture"
122	fi
123	if ! c++ -m32 -dM -E - < /dev/null 2>/dev/null > ./def32; then
124		atf_skip "c++ -m32 not supported on this architecture"
125	else
126		if fgrep -q _LP64 ./def32; then
127			atf_fail "c++ -m32 does not generate netbsd32 binaries"
128		fi
129	fi
130
131	cat > test.cpp << EOF
132#include <cstdio>
133#include <thread>
134#include <mutex>
135std::once_flag flag;
136int main(void) {
137        std::call_once(flag, [](){ printf("hello, world!\n"); });
138        return 0;
139}
140EOF
141	atf_check -s exit:0 -o ignore -e ignore c++ -static -m32 -pg -o call_once test.cpp -pthread
142	atf_check -s exit:0 -o inline:"hello, world!\n" ./call_once
143}
144
145call_once_pic_body() {
146	cat > test.cpp << EOF
147#include <stdlib.h>
148int callpic(void);
149int main(void) {callpic();exit(0);}
150EOF
151	cat > pic.cpp << EOF
152#include <cstdio>
153#include <thread>
154#include <mutex>
155std::once_flag flag;
156int callpic(void) {
157        std::call_once(flag, [](){ printf("hello, world!\n"); });
158        return 0;
159}
160EOF
161
162	atf_check -s exit:0 -o ignore -e ignore \
163	    c++ -fPIC -shared -o libtest.so pic.cpp
164	atf_check -s exit:0 -o ignore -e ignore \
165	    c++ -o call_once test.cpp -L. -ltest -pthread
166
167	export LD_LIBRARY_PATH=.
168	atf_check -s exit:0 -o inline:"hello, world!\n" ./call_once
169}
170
171call_once_pic_32_body() {
172	# check whether this arch is 64bit
173	if ! c++ -dM -E - < /dev/null | fgrep -q _LP64; then
174		atf_skip "this is not a 64 bit architecture"
175	fi
176	if ! c++ -m32 -dM -E - < /dev/null 2>/dev/null > ./def32; then
177		atf_skip "c++ -m32 not supported on this architecture"
178	else
179		if fgrep -q _LP64 ./def32; then
180			atf_fail "c++ -m32 does not generate netbsd32 binaries"
181		fi
182	fi
183
184	cat > test.cpp << EOF
185#include <stdlib.h>
186int callpic(void);
187int main(void) {callpic();exit(0);}
188EOF
189	cat > pic.cpp << EOF
190#include <cstdio>
191#include <thread>
192#include <mutex>
193std::once_flag flag;
194int callpic(void) {
195        std::call_once(flag, [](){ printf("hello, world!\n"); });
196        return 0;
197}
198EOF
199
200	atf_check -s exit:0 -o ignore -e ignore \
201	    c++ -m32 -fPIC -shared -o libtest.so pic.cpp
202	atf_check -s exit:0 -o ignore -e ignore \
203	    c++ -m32 -o call_once test.cpp -L. -ltest -pthread
204
205	export LD_LIBRARY_PATH=.
206	atf_check -s exit:0 -o inline:"hello, world!\n" ./call_once
207}
208
209call_once_pic_profile_body() {
210	cat > test.cpp << EOF
211#include <stdlib.h>
212int callpic(void);
213int main(void) {callpic();exit(0);}
214EOF
215	cat > pic.cpp << EOF
216#include <cstdio>
217#include <thread>
218#include <mutex>
219std::once_flag flag;
220int callpic(void) {
221        std::call_once(flag, [](){ printf("hello, world!\n"); });
222        return 0;
223}
224EOF
225
226	atf_check -s exit:0 -o ignore -e ignore \
227	    c++ -pg -fPIC -shared -o libtest.so pic.cpp
228	atf_check -s exit:0 -o ignore -e ignore \
229	    c++ -pg -o call_once test.cpp -L. -ltest -pthread
230
231	export LD_LIBRARY_PATH=.
232	atf_check -s exit:0 -o inline:"hello, world!\n" ./call_once
233}
234
235call_once_pic_profile_32_body() {
236	# check whether this arch is 64bit
237	if ! c++ -dM -E - < /dev/null | fgrep -q _LP64; then
238		atf_skip "this is not a 64 bit architecture"
239	fi
240	if ! c++ -m32 -dM -E - < /dev/null 2>/dev/null > ./def32; then
241		atf_skip "c++ -m32 not supported on this architecture"
242	else
243		if fgrep -q _LP64 ./def32; then
244			atf_fail "c++ -m32 does not generate netbsd32 binaries"
245		fi
246	fi
247
248	cat > test.cpp << EOF
249#include <stdlib.h>
250int callpic(void);
251int main(void) {callpic();exit(0);}
252EOF
253	cat > pic.cpp << EOF
254#include <cstdio>
255#include <thread>
256#include <mutex>
257std::once_flag flag;
258int callpic(void) {
259        std::call_once(flag, [](){ printf("hello, world!\n"); });
260        return 0;
261}
262EOF
263
264	atf_check -s exit:0 -o ignore -e ignore \
265	    c++ -m32 -pg -fPIC -shared -o libtest.so pic.cpp
266	atf_check -s exit:0 -o ignore -e ignore \
267	    c++ -m32 -pg -o call_once test.cpp -L. -ltest -pthread
268
269	export LD_LIBRARY_PATH=.
270	atf_check -s exit:0 -o inline:"hello, world!\n" ./call_once
271}
272
273call_once_pie_body() {
274	# check whether this arch supports -pie
275	if ! c++ -pie -dM -E - < /dev/null 2>/dev/null >/dev/null; then
276		atf_skip "c++ -pie not supported on this architecture"
277	fi
278	cat > test.cpp << EOF
279#include <cstdio>
280#include <thread>
281#include <mutex>
282std::once_flag flag;
283int main(void) {
284        std::call_once(flag, [](){ printf("hello, world!\n"); });
285        return 0;
286}
287EOF
288	atf_check -s exit:0 -o ignore -e ignore c++ -fpie -pie -o call_once test.cpp -pthread
289	atf_check -s exit:0 -o inline:"hello, world!\n" ./call_once
290}
291
292call_once_32_body() {
293	# check whether this arch is 64bit
294	if ! c++ -dM -E - < /dev/null | fgrep -q _LP64; then
295		atf_skip "this is not a 64 bit architecture"
296	fi
297	if ! c++ -m32 -dM -E - < /dev/null 2>/dev/null > ./def32; then
298		atf_skip "c++ -m32 not supported on this architecture"
299	else
300		if fgrep -q _LP64 ./def32; then
301			atf_fail "c++ -m32 does not generate netbsd32 binaries"
302		fi
303	fi
304
305	cat > test.cpp << EOF
306#include <cstdio>
307#include <thread>
308#include <mutex>
309std::once_flag flag;
310int main(void) {
311        std::call_once(flag, [](){ printf("hello, world!\n"); });
312        return 0;
313}
314EOF
315	atf_check -s exit:0 -o ignore -e ignore c++ -o call_once_32 -m32 test.cpp -pthread
316	atf_check -s exit:0 -o ignore -e ignore c++ -o call_once_64 test.cpp -pthread
317	file -b ./call_once_32 > ./ftype32
318	file -b ./call_once_64 > ./ftype64
319	if diff ./ftype32 ./ftype64 >/dev/null; then
320		atf_fail "generated binaries do not differ"
321	fi
322	echo "32bit binaries on this platform are:"
323	cat ./ftype32
324	echo "While native (64bit) binaries are:"
325	cat ./ftype64
326	atf_check -s exit:0 -o inline:"hello, world!\n" ./call_once_32
327
328	# do another test with static 32bit binaries
329	cat > test.cpp << EOF
330#include <cstdio>
331#include <thread>
332#include <mutex>
333std::once_flag flag;
334int main(void) {
335        std::call_once(flag, [](){ printf("hello, world!\n"); });
336        return 0;
337}
338EOF
339	atf_check -s exit:0 -o ignore -e ignore c++ -o call_once -m32 -pthread \
340	    -static test.cpp
341	atf_check -s exit:0 -o inline:"hello, world!\n" ./call_once
342}
343
344call_once_static_body() {
345	cat > test.cpp << EOF
346#include <cstdio>
347#include <thread>
348#include <mutex>
349std::once_flag flag;
350int main(void) {
351        std::call_once(flag, [](){ printf("hello, world!\n"); });
352        return 0;
353}
354EOF
355	atf_check -s exit:0 -o ignore -e ignore c++ -static -o call_once test.cpp -pthread
356	atf_check -s exit:0 -o inline:"hello, world!\n" ./call_once
357}
358
359atf_init_test_cases()
360{
361
362	atf_add_test_case call_once
363	atf_add_test_case call_once_profile
364	atf_add_test_case call_once_pic
365	atf_add_test_case call_once_pie
366	atf_add_test_case call_once_32
367	atf_add_test_case call_once_static
368	atf_add_test_case call_once_pic_32
369	atf_add_test_case call_once_pic_profile
370	atf_add_test_case call_once_pic_profile_32
371	atf_add_test_case call_once_profile_32
372}
373